using System; using System.Reflection; using System.ComponentModel; using System.Linq; using System.Collections.Generic; using System.Linq.Expressions; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; namespace EasyDevCore.Common { /// /// Reflection Tools /// public static class ReflectionHelper { /// /// Creates the object. /// /// Name of the type. /// The args. /// public static object CreateInstance(string typeName, params object[] args) => CreateInstance(Type.GetType(typeName, true, true), args); /// /// Creates the object. /// /// /// The arguments. /// public static T CreateInstance(params object[] args) => (T)CreateInstance(typeof(T), args); /// /// Creates the object. /// /// The type. /// The arguments. /// ///
///
public static object CreateInstance(this Type type, params object[] args) { if (args.Length > 0) { return Activator.CreateInstance(type, args); } else { return Activator.CreateInstance(type); } } /// /// Finds the types. /// /// The search types. /// if set to true [is class]. /// if set to true [is abstract]. /// if set to true [is interface]. /// The assembly predicate. /// The type predicate. /// public static IList FindTypes(Type[] searchTypes, bool? isClass = null, bool? isAbstract = null, bool? isInterface = null, Func assemblyPredicate = null, Func typePredicate = null) { IEnumerable assemblies = AppDomain.CurrentDomain.GetAssemblies(); if (assemblyPredicate != null) assemblies = assemblies.Where(assemblyPredicate); IEnumerable types = assemblies.SelectMany(a => a.GetTypes()); bool multiType = searchTypes.Length > 1; types = types.Where(t => { bool ok = t.IsPublic && ((!multiType && searchTypes[0].IsAssignableFrom(t)) || (multiType && searchTypes.Any(st => st.IsAssignableFrom(t)))); if(isClass.HasValue && t.IsClass != isClass.Value) ok = false; if(isAbstract.HasValue && t.IsAbstract != isAbstract.Value) ok = false; if(isInterface.HasValue && t.IsInterface != isInterface.Value) ok = false; return ok; }); if (typePredicate != null) types = types.Where(typePredicate); return types.ToList(); } /// /// Finds the types. /// /// /// if set to true [is class]. /// if set to true [is abstract]. /// if set to true [is interface]. /// The assembly predicate. /// The type predicate. /// public static IList FindTypes(bool? isClass = null, bool? isAbstract = null, bool? isInterface = null, Func assemblyPredicate = null, Func typePredicate = null) { Type[] types = new Type[1]; types[0] = typeof(T); return FindTypes(types, isClass, isAbstract, isInterface, assemblyPredicate, typePredicate); } /// /// Gets the expression custom attribute. /// /// The type of the odel type. /// The type of the alue type. /// /// The expression. /// /// /// public static T GetExpressionCustomAttribute(this Expression> expression) { MemberExpression member = expression.Body as MemberExpression; if (member == null) throw new ArgumentException(string.Format("Expression '{0}' refers to a method, not a property.", expression.ToString())); PropertyInfo propInfo = member.Member as PropertyInfo; if (propInfo == null) throw new ArgumentException(string.Format("Expression '{0}' refers to a field, not a property.", expression.ToString())); var attributes = propInfo.GetCustomAttributes(typeof(T), true); if (attributes.Length > 0) return (T)attributes[0]; return default(T); } /// /// Gets the expression value. /// /// The type of the model type. /// The type of the value type. /// The expression. /// The source. /// ValueType. /// /// public static ValueType GetExpressionValue(this Expression> expression, ModelType source) { MemberExpression member = expression.Body as MemberExpression; if (member == null) throw new ArgumentException(string.Format("Expression '{0}' refers to a method, not a property.", expression.ToString())); PropertyInfo propInfo = member.Member as PropertyInfo; if (propInfo == null) throw new ArgumentException(string.Format("Expression '{0}' refers to a field, not a property.", expression.ToString())); if (source == null) throw new ArgumentNullException(nameof(source)); return (ValueType)source.GetPropertyValue(propInfo.Name); } /// /// Gets the name of the member. /// /// /// The member expression. /// public static string GetMemberName(Expression> memberExpression) { MemberExpression expressionBody = (MemberExpression)memberExpression.Body; return expressionBody.Member.Name; } /// /// Gets the PropertyInfo for the TargetProperty. /// /// The target object. /// The target property. /// Type of the return. /// The param types (System.Type.EmptyTypes = no parameters). /// public static PropertyInfo GetPropertyInfo(this object target, string targetProperty, Type returnType = null, Type[] paramTypes = null) { if ((returnType != null) || (paramTypes != null)) { return target.GetType().GetProperty(targetProperty, BindingFlags.Public | BindingFlags.Instance, null, returnType, paramTypes, null); } else { return target.GetType().GetProperty(targetProperty); } } /// /// Gets the property infos. /// /// The type. /// public static PropertyInfo[] GetPropertyInfos(this Type type) { return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public).ToArray(); } /// /// Gets multi PropertyInfo for the TargetProperty. /// /// The target. /// public static PropertyInfo[] GetPropertyInfos(this object target) { return GetPropertyInfos(target.GetType()); } /// /// Gets the method info. /// /// The target. /// The target method. /// The param types (System.Type.EmptyTypes = no parameters). /// public static MethodInfo GetMethodInfo(this object target, string targetMethod, Type[] paramTypes = null) { if (paramTypes != null) { return target.GetType().GetMethod(targetMethod, BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, paramTypes, null); } else { return target.GetType().GetMethod(targetMethod); } } /// /// Gets the method info. /// /// The target. /// The target method. /// public static MethodInfo[] GetMethodInfos(this object target, string targetMethod) { return target.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) .Where((mi) => mi.Name == targetMethod).ToArray(); } /// /// Invokes the method. /// /// The target. /// The target method. /// The args. /// public static object InvokeMethod(this T target, string targetMethod, params object[] args) where T: class { MethodInfo methodInfo = GetMethodInfo(target, targetMethod); if (methodInfo == null) return null; return methodInfo.Invoke(target, args); } /// /// Invokes the method asynchronous. /// /// /// /// The target. /// The target method. /// The arguments. /// public static async Task InvokeMethodAsync(this T target, string targetMethod, params object[] args) where T : class { dynamic awaitable = (R)target.InvokeMethod(targetMethod, args); await awaitable; return awaitable.GetAwaiter().GetResult(); } /// /// Checks the attribute exists. /// /// /// The target. /// public static bool CheckAttributeExists(this object target) where T : Attribute { return Attribute.IsDefined(target.GetType().Assembly, typeof(T)); } /// /// Gets the attribute. /// /// /// The target. /// public static T GetAttribute(this object target) where T : Attribute { return (T)Attribute.GetCustomAttribute(target.GetType().Assembly, typeof(T)); } /// /// Gets the attributes. /// /// /// The target. /// public static T[] GetAttributes(this object target) where T : Attribute { return (T[])Attribute.GetCustomAttributes(target.GetType().Assembly, typeof(T)); } /// /// Checks the property exists. /// /// The target. /// The target property. /// public static bool CheckPropertyExist(this object target, string targetProperty) { if (target is System.Dynamic.ExpandoObject) { return ((IDictionary)target).ContainsKey(targetProperty); } else { object obj = target; PropertyDescriptor prop; while (true) { if (targetProperty.Contains(".")) { string parentProperty = targetProperty.Substring(0, targetProperty.IndexOf(".")); prop = TypeDescriptor.GetProperties(obj)[parentProperty]; obj = prop.GetValue(obj); targetProperty = targetProperty.Substring(parentProperty.Length + 1); } else { prop = TypeDescriptor.GetProperties(obj)[targetProperty]; break; } } return (prop != null); } } /// /// Gets the property values. /// /// The target. /// public static IDictionary GetPropertyValues(this object target) { Dictionary valuePairs = new Dictionary(); foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(target)) { valuePairs.Add(prop.Name, prop.GetValue(target)); } return valuePairs; } /// /// Gets the property value for the TargetProperty. /// /// The target object. /// The target property. /// The property value. public static object GetPropertyValue(this object target, string targetProperty) { if (target is System.Dynamic.ExpandoObject) { if (CheckPropertyExist(target, targetProperty)) { return ((IDictionary)target)[targetProperty]; } return null; } else { object obj = target; PropertyDescriptor prop; while (true) { if (targetProperty.Contains(".")) { string parentProperty = targetProperty.Substring(0, targetProperty.IndexOf(".")); prop = TypeDescriptor.GetProperties(obj)[parentProperty]; obj = prop.GetValue(obj); targetProperty = targetProperty.Substring(parentProperty.Length + 1); } else { prop = TypeDescriptor.GetProperties(obj)[targetProperty]; break; } } return (prop == null) ? null : prop.GetValue(obj); } } /// /// Gets the indexer value. /// /// The target. /// The index value. /// The target parent property. /// public static object GetIndexerValue(this object target, object indexValue, string targetParentProperty = "") { object obj = target; PropertyDescriptor prop; PropertyInfo pi; while (true) { if (targetParentProperty.Contains(".")) { string parentProperty = targetParentProperty.Substring(0, targetParentProperty.IndexOf(".")); prop = TypeDescriptor.GetProperties(obj)[parentProperty]; obj = prop.GetValue(obj); targetParentProperty = targetParentProperty.Substring(parentProperty.Length + 1); } else { pi = GetPropertyInfo(obj, "Item", null, new Type[] { indexValue.GetType() }); break; } } return (pi == null) ? null : pi.GetValue(obj, new object[] { indexValue }); } /// /// Gets the indexer value. /// /// /// The target. /// The index value. /// The target parent property. /// public static T GetIndexerValue(this object target, object indexValue, string targetParentProperty = "") { return (T)GetIndexerValue(target, indexValue, targetParentProperty); } /// /// Sets the indexer value. /// /// The target. /// The index value. /// The value. /// The target parent property. public static void SetIndexerValue(this T target, object indexValue, object value, string targetParentProperty = "") where T: class { object obj = target; PropertyDescriptor prop; PropertyInfo pi; while (true) { if (targetParentProperty.Contains(".")) { string parentProperty = targetParentProperty.Substring(0, targetParentProperty.IndexOf(".")); prop = TypeDescriptor.GetProperties(obj)[parentProperty]; obj = prop.GetValue(obj); targetParentProperty = targetParentProperty.Substring(parentProperty.Length + 1); } else { pi = GetPropertyInfo(obj, "Item", null, new Type[] { indexValue.GetType() }); break; } } pi.SetValue(obj, value, new object[] { indexValue }); } /// /// Gets the property value for the TargetProperty. /// /// The type of the property. /// The target object. /// The target property. /// The property value. public static T GetPropertyValue(this object target, string targetProperty) { return (T)(GetPropertyValue(target, targetProperty) ?? default(T)); } /// /// Gets the property value for the TargetProperty and convert to T, if not success uses default value. /// /// The type of the property. /// The target object. /// The target property. /// The default value. /// /// The property value. /// public static T GetPropertyValue(this object target, string targetProperty, T defaultValue) { if (CheckPropertyExist(target, targetProperty)) { var value = GetPropertyValue(target, targetProperty); return value == null ? defaultValue : value.ConvertTo(defaultValue); } else { return defaultValue; } } /// /// Sets the property value for the TargetProperty. /// /// The target object. /// The target property. /// The value to set. public static void SetPropertyValue(this T target, string targetProperty, object value) { if (target == null) throw new ArgumentNullException("target", "Target object can not be Null."); if (target is System.Dynamic.ExpandoObject) { ((IDictionary)target)[targetProperty] = value; } else { object obj = target; PropertyDescriptor prop; while (true) { if (targetProperty.Contains(".")) { string parentProperty = targetProperty.Substring(0, targetProperty.IndexOf(".")); prop = TypeDescriptor.GetProperties(obj)[parentProperty]; obj = prop.GetValue(obj); targetProperty = targetProperty.Substring(parentProperty.Length + 1); } else { prop = TypeDescriptor.GetProperties(obj)[targetProperty]; break; } } if (value == null) prop.SetValue(obj, null); else { SetPropertyValue(target, prop, value); } } } /// /// Sets the property value. /// /// The type of the model. /// The model. /// The property. /// The value. public static void SetPropertyValue(TModel model, PropertyDescriptor prop, object value) { if (value == null) { prop.SetValue(model, null); return; } Type pType = prop.PropertyType.GetUnderlyingType(); Type vType = value.GetType().GetUnderlyingType(); if (pType != null && (pType.Equals(vType) || pType.FullName == "System.Object")) { // types match, just copy value prop.SetValue(model, value); } else { // types don't match, try to coerce if (pType.Equals(typeof(Guid))) { prop.SetValue(model, new Guid(value.ToString())); } else if (pType.IsEnum && vType.Equals(typeof(string))) prop.SetValue(model, Enum.Parse(pType, value.ToString())); else if (pType.IsEnum && vType.IsNumericType()) prop.SetValue(model, value.ConvertTo()); else prop.SetValue(model, Convert.ChangeType(value, pType)); } } /// /// Invokes the generic method. /// /// The type. /// Type of the interface. /// Name of the method. /// The arguments. /// public static object InvokeGenericStaticMethod(this Type type, Type interfaceType, string methodName, params object[] args) { MethodInfo mi = type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).First(f => f.Name == methodName); MethodInfo miConstructed = mi.MakeGenericMethod(interfaceType); return miConstructed.Invoke(null, args != null && args.Length > 0 ? args : null); } /// /// Invokes the generic static method asynchronous. /// /// The type. /// Type of the interface. /// Name of the method. /// The arguments. /// public static async Task InvokeGenericStaticMethodAsync(this Type type, Type interfaceType, string methodName, params object[] args) { MethodInfo mi = type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).First(f => f.Name == methodName); MethodInfo miConstructed = mi.MakeGenericMethod(interfaceType); Task result = (Task)miConstructed.Invoke(null, args != null && args.Length > 0 ? args : null); return await result; } /// /// Invokes the generic method. /// /// The object. /// Type of the interface. /// Name of the method. /// The arguments. /// public static object InvokeGenericMethod(this object obj, Type interfaceType, string methodName, params object[] args) { MethodInfo mi = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).First(f => f.Name == methodName); MethodInfo miConstructed = mi.MakeGenericMethod(interfaceType); return miConstructed.Invoke(obj, args != null && args.Length > 0 ? args : null); } /// /// Invokes the generic method asynchronous. /// /// The object. /// Type of the interface. /// Name of the method. /// The arguments. /// public static async Task InvokeGenericMethodAsync(this object obj, Type interfaceType, string methodName, params object[] args) { MethodInfo mi = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).First(f => f.Name == methodName); MethodInfo miConstructed = mi.MakeGenericMethod(interfaceType); Task result = (Task)miConstructed.Invoke(obj, args != null && args.Length > 0 ? args : null); return await result; } } }