123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645 |
- 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
- {
- /// <summary>
- /// Reflection Tools
- /// </summary>
- public static class ReflectionHelper
- {
- /// <summary>
- /// Creates the object.
- /// </summary>
- /// <param name="typeName">Name of the type.</param>
- /// <param name="args">The args.</param>
- /// <returns></returns>
- public static object CreateInstance(string typeName, params object[] args) => CreateInstance(Type.GetType(typeName, true, true), args);
- /// <summary>
- /// Creates the object.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="args">The arguments.</param>
- /// <returns></returns>
- public static T CreateInstance<T>(params object[] args) => (T)CreateInstance(typeof(T), args);
- /// <summary>
- /// Creates the object.
- /// </summary>
- /// <param name="type">The type.</param>
- /// <param name="args">The arguments.</param>
- /// <returns>
- /// <br />
- /// </returns>
- public static object CreateInstance(this Type type, params object[] args)
- {
- if (args.Length > 0)
- {
- return Activator.CreateInstance(type, args);
- }
- else
- {
- return Activator.CreateInstance(type);
- }
- }
- /// <summary>
- /// Finds the types.
- /// </summary>
- /// <param name="searchTypes">The search types.</param>
- /// <param name="isClass">if set to <c>true</c> [is class].</param>
- /// <param name="isAbstract">if set to <c>true</c> [is abstract].</param>
- /// <param name="isInterface">if set to <c>true</c> [is interface].</param>
- /// <param name="assemblyPredicate">The assembly predicate.</param>
- /// <param name="typePredicate">The type predicate.</param>
- /// <returns></returns>
- public static IList<Type> FindTypes(Type[] searchTypes, bool? isClass = null, bool? isAbstract = null, bool? isInterface = null, Func<Assembly, bool> assemblyPredicate = null, Func<Type, bool> typePredicate = null)
- {
- IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies();
- if (assemblyPredicate != null) assemblies = assemblies.Where(assemblyPredicate);
- IEnumerable<Type> 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();
- }
- /// <summary>
- /// Finds the types.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="isClass">if set to <c>true</c> [is class].</param>
- /// <param name="isAbstract">if set to <c>true</c> [is abstract].</param>
- /// <param name="isInterface">if set to <c>true</c> [is interface].</param>
- /// <param name="assemblyPredicate">The assembly predicate.</param>
- /// <param name="typePredicate">The type predicate.</param>
- /// <returns></returns>
- public static IList<Type> FindTypes<T>(bool? isClass = null, bool? isAbstract = null, bool? isInterface = null, Func<Assembly, bool> assemblyPredicate = null, Func<Type, bool> typePredicate = null)
- {
- Type[] types = new Type[1];
- types[0] = typeof(T);
- return FindTypes(types, isClass, isAbstract, isInterface, assemblyPredicate, typePredicate);
- }
- /// <summary>
- /// Gets the expression custom attribute.
- /// </summary>
- /// <typeparam name="ModelType">The type of the odel type.</typeparam>
- /// <typeparam name="ValueType">The type of the alue type.</typeparam>
- /// <typeparam name="T"></typeparam>
- /// <param name="expression">The expression.</param>
- /// <returns></returns>
- /// <exception cref="System.ArgumentException">
- /// </exception>
- public static T GetExpressionCustomAttribute<ModelType, ValueType, T>(this Expression<Func<ModelType, ValueType>> 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);
- }
- /// <summary>
- /// Gets the expression value.
- /// </summary>
- /// <typeparam name="ModelType">The type of the model type.</typeparam>
- /// <typeparam name="ValueType">The type of the value type.</typeparam>
- /// <param name="expression">The expression.</param>
- /// <param name="source">The source.</param>
- /// <returns>ValueType.</returns>
- /// <exception cref="ArgumentException">
- /// </exception>
- public static ValueType GetExpressionValue<ModelType, ValueType>(this Expression<Func<ModelType, ValueType>> 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);
- }
- /// <summary>
- /// Gets the name of the member.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="memberExpression">The member expression.</param>
- /// <returns></returns>
- public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
- {
- MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
- return expressionBody.Member.Name;
- }
- /// <summary>
- /// Gets the PropertyInfo for the TargetProperty.
- /// </summary>
- /// <param name="target">The target object.</param>
- /// <param name="targetProperty">The target property.</param>
- /// <param name="returnType">Type of the return.</param>
- /// <param name="paramTypes">The param types (System.Type.EmptyTypes = no parameters).</param>
- /// <returns></returns>
- 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);
- }
- }
- /// <summary>
- /// Gets the property infos.
- /// </summary>
- /// <param name="type">The type.</param>
- /// <returns></returns>
- public static PropertyInfo[] GetPropertyInfos(this Type type)
- {
- return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public).ToArray<PropertyInfo>();
- }
- /// <summary>
- /// Gets multi PropertyInfo for the TargetProperty.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <returns></returns>
- public static PropertyInfo[] GetPropertyInfos(this object target)
- {
- return GetPropertyInfos(target.GetType());
- }
- /// <summary>
- /// Gets the method info.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="targetMethod">The target method.</param>
- /// <param name="paramTypes">The param types (System.Type.EmptyTypes = no parameters).</param>
- /// <returns></returns>
- 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);
- }
- }
- /// <summary>
- /// Gets the method info.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="targetMethod">The target method.</param>
- /// <returns></returns>
- 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<MethodInfo>();
- }
- /// <summary>
- /// Invokes the method.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="targetMethod">The target method.</param>
- /// <param name="args">The args.</param>
- /// <returns></returns>
- public static object InvokeMethod<T>(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);
- }
- /// <summary>
- /// Invokes the method asynchronous.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <typeparam name="R"></typeparam>
- /// <param name="target">The target.</param>
- /// <param name="targetMethod">The target method.</param>
- /// <param name="args">The arguments.</param>
- /// <returns></returns>
- public static async Task<R> InvokeMethodAsync<T, R>(this T target, string targetMethod, params object[] args) where T : class
- {
- dynamic awaitable = (R)target.InvokeMethod(targetMethod, args);
- await awaitable;
- return awaitable.GetAwaiter().GetResult();
- }
- /// <summary>
- /// Checks the attribute exists.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="target">The target.</param>
- /// <returns></returns>
- public static bool CheckAttributeExists<T>(this object target)
- where T : Attribute
- {
- return Attribute.IsDefined(target.GetType().Assembly, typeof(T));
- }
- /// <summary>
- /// Gets the attribute.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="target">The target.</param>
- /// <returns></returns>
- public static T GetAttribute<T>(this object target)
- where T : Attribute
- {
- return (T)Attribute.GetCustomAttribute(target.GetType().Assembly, typeof(T));
- }
- /// <summary>
- /// Gets the attributes.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="target">The target.</param>
- /// <returns></returns>
- public static T[] GetAttributes<T>(this object target)
- where T : Attribute
- {
- return (T[])Attribute.GetCustomAttributes(target.GetType().Assembly, typeof(T));
- }
- /// <summary>
- /// Checks the property exists.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="targetProperty">The target property.</param>
- /// <returns></returns>
- public static bool CheckPropertyExist(this object target, string targetProperty)
- {
- if (target is System.Dynamic.ExpandoObject)
- {
- return ((IDictionary<String, object>)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);
- }
- }
- /// <summary>
- /// Gets the property values.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <returns></returns>
- public static IDictionary<string, object> GetPropertyValues(this object target)
- {
- Dictionary<string, object> valuePairs = new Dictionary<string, object>();
- foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(target))
- {
- valuePairs.Add(prop.Name, prop.GetValue(target));
- }
- return valuePairs;
- }
- /// <summary>
- /// Gets the property value for the TargetProperty.
- /// </summary>
- /// <param name="target">The target object.</param>
- /// <param name="targetProperty">The target property.</param>
- /// <returns>The property value.</returns>
- public static object GetPropertyValue(this object target, string targetProperty)
- {
- if (target is System.Dynamic.ExpandoObject)
- {
- if (CheckPropertyExist(target, targetProperty))
- {
- return ((IDictionary<String, object>)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);
- }
- }
- /// <summary>
- /// Gets the indexer value.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="indexValue">The index value.</param>
- /// <param name="targetParentProperty">The target parent property.</param>
- /// <returns></returns>
- 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 });
- }
- /// <summary>
- /// Gets the indexer value.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="target">The target.</param>
- /// <param name="indexValue">The index value.</param>
- /// <param name="targetParentProperty">The target parent property.</param>
- /// <returns></returns>
- public static T GetIndexerValue<T>(this object target, object indexValue, string targetParentProperty = "")
- {
- return (T)GetIndexerValue(target, indexValue, targetParentProperty);
- }
- /// <summary>
- /// Sets the indexer value.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="indexValue">The index value.</param>
- /// <param name="value">The value.</param>
- /// <param name="targetParentProperty">The target parent property.</param>
- public static void SetIndexerValue<T>(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 });
- }
- /// <summary>
- /// Gets the property value for the TargetProperty.
- /// </summary>
- /// <typeparam name="T">The type of the property.</typeparam>
- /// <param name="target">The target object.</param>
- /// <param name="targetProperty">The target property.</param>
- /// <returns>The property value.</returns>
- public static T GetPropertyValue<T>(this object target, string targetProperty)
- {
- return (T)(GetPropertyValue(target, targetProperty) ?? default(T));
- }
- /// <summary>
- /// Gets the property value for the TargetProperty and convert to T, if not success uses default value.
- /// </summary>
- /// <typeparam name="T">The type of the property.</typeparam>
- /// <param name="target">The target object.</param>
- /// <param name="targetProperty">The target property.</param>
- /// <param name="defaultValue">The default value.</param>
- /// <returns>
- /// The property value.
- /// </returns>
- public static T GetPropertyValue<T>(this object target, string targetProperty, T defaultValue)
- {
- if (CheckPropertyExist(target, targetProperty))
- {
- var value = GetPropertyValue(target, targetProperty);
- return value == null ? defaultValue : value.ConvertTo<T>(defaultValue);
- }
- else
- {
- return defaultValue;
- }
- }
-
- /// <summary>
- /// Sets the property value for the TargetProperty.
- /// </summary>
- /// <param name="target">The target object.</param>
- /// <param name="targetProperty">The target property.</param>
- /// <param name="value">The value to set.</param>
- public static void SetPropertyValue<T>(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<String, object>)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);
- }
- }
- }
- /// <summary>
- /// Sets the property value.
- /// </summary>
- /// <typeparam name="TModel">The type of the model.</typeparam>
- /// <param name="model">The model.</param>
- /// <param name="prop">The property.</param>
- /// <param name="value">The value.</param>
- public static void SetPropertyValue<TModel>(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<int>());
- else
- prop.SetValue(model, Convert.ChangeType(value, pType));
- }
- }
- /// <summary>
- /// Invokes the generic method.
- /// </summary>
- /// <param name="type">The type.</param>
- /// <param name="interfaceType">Type of the interface.</param>
- /// <param name="methodName">Name of the method.</param>
- /// <param name="args">The arguments.</param>
- /// <returns></returns>
- 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);
- }
- /// <summary>
- /// Invokes the generic static method asynchronous.
- /// </summary>
- /// <param name="type">The type.</param>
- /// <param name="interfaceType">Type of the interface.</param>
- /// <param name="methodName">Name of the method.</param>
- /// <param name="args">The arguments.</param>
- /// <returns></returns>
- public static async Task<T> InvokeGenericStaticMethodAsync<T>(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<T> result = (Task<T>)miConstructed.Invoke(null, args != null && args.Length > 0 ? args : null);
- return await result;
- }
- /// <summary>
- /// Invokes the generic method.
- /// </summary>
- /// <param name="obj">The object.</param>
- /// <param name="interfaceType">Type of the interface.</param>
- /// <param name="methodName">Name of the method.</param>
- /// <param name="args">The arguments.</param>
- /// <returns></returns>
- 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);
- }
- /// <summary>
- /// Invokes the generic method asynchronous.
- /// </summary>
- /// <param name="obj">The object.</param>
- /// <param name="interfaceType">Type of the interface.</param>
- /// <param name="methodName">Name of the method.</param>
- /// <param name="args">The arguments.</param>
- /// <returns></returns>
- public static async Task<object> 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<object> result = (Task<object>)miConstructed.Invoke(obj, args != null && args.Length > 0 ? args : null);
- return await result;
- }
- }
- }
|