using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Cryville.Common { /// /// Provides a set of methods for refletion. /// public static class ReflectionHelper { static readonly Type[] emptyTypeArray = {}; /// /// Gets the parameterless constructor of a type. /// /// The type. /// The parameterless constructor of the type. public static ConstructorInfo GetEmptyConstructor(Type type) { return type.GetConstructor(emptyTypeArray); } static readonly object[] emptyObjectArray = {}; /// /// Invokes the parameterless constructor of a type and returns the result. /// /// The type. /// The created instance. public static object InvokeEmptyConstructor(Type type) { return GetEmptyConstructor(type).Invoke(emptyObjectArray); } /// /// Tries to find a member with the specified attribute type in a type. /// /// The attribute type. /// The type containing the member with the specified attribute type. /// The member. /// Whether the member is found. public static bool TryFindMemberWithAttribute(Type t, out MemberInfo mi) where T : Attribute { try { mi = FindMemberWithAttribute(t); return true; } catch (MissingMemberException) { mi = null; return false; } } /// /// Finds a member with the specified attribute type in a type. /// /// The attribute type. /// The type containing the member with the specified attribute type. /// /// The member is not found or multiple members are found. public static MemberInfo FindMemberWithAttribute(Type type) where T : Attribute { var mil = type.FindMembers( MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, (m, o) => m.GetCustomAttributes(typeof(T), true).Length != 0, null ); if (mil.Length != 1) throw new MissingMemberException(type.Name, typeof(T).Name); return mil[0]; } /// /// Gets whether a type is a . /// /// The type. /// Whether the type is a . public static bool IsGenericDictionary(Type type) { return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>); } /// /// Gets the member from a type with the specified name. /// /// The type. /// The name of the member. /// The member. /// The member is not found or multiple members are found. public static MemberInfo GetMember(Type type, string name) { var mil = type.GetMember( name, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance ); if (mil.Length != 1) throw new MissingMemberException(type.Name, name); return mil[0]; } /// /// Gets the type of a member. /// /// The member. /// The type of the member. /// is not a field or a property. public static Type GetMemberType(MemberInfo mi) { if (mi is FieldInfo) return ((FieldInfo)mi).FieldType; if (mi is PropertyInfo) return ((PropertyInfo)mi).PropertyType; else throw new ArgumentException("Member is not field or property."); } /// /// Gets the value of a member of an object. /// /// The member. /// The object. /// The value. /// is not a field or a property. public static object GetValue(MemberInfo mi, object obj) { if (mi is FieldInfo) return ((FieldInfo)mi).GetValue(obj); else if (mi is PropertyInfo) return ((PropertyInfo)mi).GetValue(obj, new object[]{}); else throw new ArgumentException(); } /// /// Sets the value of a member of an object. /// /// The member. /// The object. /// The value. /// An optional binder to convert the value. /// is not a field or a property. public static void SetValue(MemberInfo mi, object obj, object value, Binder binder = null) { if (mi is FieldInfo) ((FieldInfo)mi).SetValue(obj, value, BindingFlags.Default, binder, null); else if (mi is PropertyInfo) ((PropertyInfo)mi).SetValue(obj, value, BindingFlags.Default, binder, emptyObjectArray, null); else throw new ArgumentException(); } /// /// Gets all the subclasses of a type in the current app domain. /// /// The type. /// An array containing all the subclasses of the type in the current app domain. public static Type[] GetSubclassesOf() where T : class { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); IEnumerable r = Enumerable.Empty(); foreach (var a in assemblies) r = r.Concat(a.GetTypes().Where( t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(T)) )); return r.ToArray(); } /// /// Gets a simple name of a type. /// /// The type. /// A simple name of the class. public static string GetSimpleName(Type type) { string result = type.Name; var typeargs = type.GetGenericArguments(); if (typeargs.Length > 0) { result = string.Format("{0}[{1}]", result, string.Join(",", from a in typeargs select GetSimpleName(a))); } return result; } /// /// Gets the namespace qualified name of a type. /// /// The type. /// The namespace qualified name of the class. public static string GetNamespaceQualifiedName(Type type) { string result = type.Namespace + "." + type.Name; var typeargs = type.GetGenericArguments(); if (typeargs.Length > 0) { result = string.Format("{0}[{1}]", result, string.Join(",", from a in typeargs select GetNamespaceQualifiedName(a))); } return result; } } }