using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; using System.Xml; using BLToolkit.EditableObjects; using BLToolkit.TypeBuilder; namespace BLToolkit.Reflection { /// /// A wrapper around the class. /// [System.Diagnostics.DebuggerDisplay("Type = {Type}")] public class TypeHelper { /// /// Initializes a new instance of the class. /// /// The Type to wrap. public TypeHelper(Type type) { if (type == null) throw new ArgumentNullException("type"); _type = type; } private readonly Type _type; /// /// Gets associated Type. /// public Type Type { get { return _type; } } /// /// Converts the supplied to a . /// /// The Type. /// A TypeHelper. public static implicit operator TypeHelper(Type type) { if (type == null) throw new ArgumentNullException("type"); return new TypeHelper(type); } /// /// Converts the supplied to a . /// /// The TypeHelper. /// A Type. public static implicit operator Type(TypeHelper typeHelper) { if (typeHelper == null) throw new ArgumentNullException("typeHelper"); return typeHelper.Type; } #region GetAttributes /// /// Returns an array of custom attributes identified by Type. /// /// The type of attribute to search for. /// Only attributes that are assignable to this type are returned. /// Specifies whether to search this member's inheritance chain /// to find the attributes. /// An array of custom attributes defined on this reflected member, /// or an array with zero (0) elements if no attributes are defined. public object[] GetCustomAttributes(Type attributeType, bool inherit) { return _type.GetCustomAttributes(attributeType, inherit); } /// /// Returns an array of custom attributes identified by Type /// including attribute's inheritance chain. /// /// The type of attribute to search for. /// Only attributes that are assignable to this type are returned. /// An array of custom attributes defined on this reflected member, /// or an array with zero (0) elements if no attributes are defined. public object[] GetCustomAttributes(Type attributeType) { return _type.GetCustomAttributes(attributeType, true); } /// /// Returns an array of all of the custom attributes. /// /// Specifies whether to search this member's inheritance chain /// to find the attributes. /// An array of custom attributes defined on this reflected member, /// or an array with zero (0) elements if no attributes are defined. public object[] GetCustomAttributes(bool inherit) { return _type.GetCustomAttributes(inherit); } /// /// Returns an array of all of the custom attributes including attributes' inheritance chain. /// /// An array of custom attributes defined on this reflected member, /// or an array with zero (0) elements if no attributes are defined. public object[] GetCustomAttributes() { return _type.GetCustomAttributes(true); } /// /// Returns an array of all custom attributes identified by Type including type's /// inheritance chain. /// /// The type of attribute to search for. /// Only attributes that are assignable to this type are returned. /// An array of custom attributes defined on this reflected member, /// or an array with zero (0) elements if no attributes are defined. public object[] GetAttributes(Type attributeType) { return GetAttributes(_type, attributeType); } /// /// Returns an array of all custom attributes including type's inheritance chain. /// /// An array of custom attributes defined on this reflected member, /// or an array with zero (0) elements if no attributes are defined. public object[] GetAttributes() { return GetAttributesInternal(); } #region Attributes cache private object[] GetAttributesInternal() { string key = _type.FullName; object[] attrs = (object[])_typeAttributes[key]; if (attrs == null) { ArrayList list = new ArrayList(); GetAttributesInternal(list, _type); _typeAttributes[key] = attrs = (object[])list.ToArray(typeof(Attribute)); } return attrs; } private static readonly Hashtable _typeAttributesTopInternal = new Hashtable(10); private static void GetAttributesInternal(ArrayList list, Type type) { object[] attrs = (object[])_typeAttributesTopInternal[type]; if (attrs != null) { list.AddRange(attrs); } else { GetAttributesTreeInternal(list, type); _typeAttributesTopInternal[type] = list.ToArray(typeof(Attribute)); } } private static readonly Hashtable _typeAttributesInternal = new Hashtable(10); private static void GetAttributesTreeInternal(ArrayList list, Type type) { object[] attrs = (object[])_typeAttributesInternal[type]; if (attrs == null) _typeAttributesInternal[type] = attrs = type.GetCustomAttributes(false); if (Common.Configuration.FilterOutBaseEqualAttributes) { for (int i = 0; i < attrs.Length; i++) if (!list.Contains(attrs[i])) list.Add(attrs[i]); } else list.AddRange(attrs); if (type.IsInterface) return; // Reflection returns interfaces for the whole inheritance chain. // So, we are going to get some hemorrhoid here to restore the inheritance sequence. // Type[] interfaces = type.GetInterfaces(); int nBaseInterfaces = type.BaseType != null? type.BaseType.GetInterfaces().Length: 0; for (int i = 0; i < interfaces.Length; i++) { Type intf = interfaces[i]; if (i < nBaseInterfaces) { bool getAttr = false; foreach (MethodInfo mi in type.GetInterfaceMap(intf).TargetMethods) { // Check if the interface is reimplemented. // if (mi.DeclaringType == type) { getAttr = true; break; } } if (getAttr == false) continue; } GetAttributesTreeInternal(list, intf); } if (type.BaseType != null && type.BaseType != typeof(object)) GetAttributesTreeInternal(list, type.BaseType); } private static readonly Hashtable _typeAttributes = new Hashtable(10); #endregion /// /// Returns an array of custom attributes applied to a type. /// /// A type instance. /// The type of attribute to search for. /// Only attributes that are assignable to this type are returned. /// An array of custom attributes applied to this type, /// or an array with zero (0) elements if no attributes have been applied. public static object[] GetAttributes(Type type, Type attributeType) { if (type == null) throw new ArgumentNullException("type"); if (attributeType == null) throw new ArgumentNullException("attributeType"); string key = type.FullName + "#" + attributeType.FullName; object[] attrs = (object[])_typeAttributes[key]; if (attrs == null) { ArrayList list = new ArrayList(); GetAttributesInternal(list, type); for (int i = 0; i < list.Count; i++) if (attributeType.IsInstanceOfType(list[i]) == false) list.RemoveAt(i--); _typeAttributes[key] = attrs = (object[])list.ToArray(typeof(Attribute)); } return attrs; } /// /// Retrieves a custom attribute applied to a type. /// /// A type instance. /// The type of attribute to search for. /// Only attributes that are assignable to this type are returned. /// A reference to the first custom attribute of type /// that is applied to element, or null if there is no such attribute. public static Attribute GetFirstAttribute(Type type, Type attributeType) { object[] attrs = new TypeHelper(type).GetAttributes(attributeType); return attrs.Length > 0? (Attribute)attrs[0]: null; } /// /// Retrieves a custom attribute applied to a type. /// /// A type instance. /// The type of attribute to search for. /// Only attributes that are assignable to this type are returned. /// A reference to the first custom attribute of type attributeType /// that is applied to element, or null if there is no such attribute. public static T GetFirstAttribute(Type type) where T : Attribute { object[] attrs = new TypeHelper(type).GetAttributes(typeof(T)); return attrs.Length > 0? (T)attrs[0]: null; } #endregion #region Property Wrappers /// /// Gets the fully qualified name of the Type, including the namespace of the Type. /// public string FullName { get { return _type.FullName; } } /// /// Gets the name of the Type. /// public string Name { get { return _type.Name; } } /// /// Gets a value indicating whether the Type is abstract and must be overridden. /// public bool IsAbstract { get { return _type.IsAbstract; } } /// /// Gets a value indicating whether the System.Type is an array. /// public bool IsArray { get { return _type.IsArray; } } /// /// Gets a value indicating whether the Type is a value type. /// public bool IsValueType { get { return _type.IsValueType; } } /// /// Gets a value indicating whether the Type is a class; that is, not a value type or interface. /// public bool IsClass { get { return _type.IsClass; } } /// /// Gets a value indicating whether the System.Type is an interface; that is, not a class or a value type. /// public bool IsInterface { get { return _type.IsInterface; } } /// /// Indicates whether the Type is serializable. /// public bool IsSerializable { get { return _type.IsSerializable; } } #endregion #region GetMethods /// /// Returns all the methods of the current Type. /// /// An array of objects representing all methods /// defined for the current Type. public MethodInfo[] GetMethods() { return _type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } /// /// Returns all the public methods of the current Type. /// /// An array of objects representing all the public methods /// defined for the current Type. public MethodInfo[] GetPublicMethods() { return _type.GetMethods(BindingFlags.Instance | BindingFlags.Public); } /// /// Searches for the methods defined for the current Type, /// using the specified binding constraints. /// /// A bitmask comprised of one or more /// that specify how the search is conducted. /// An array of objects representing all methods defined /// for the current Type that match the specified binding constraints. public MethodInfo[] GetMethods(BindingFlags flags) { return _type.GetMethods(flags); } /// /// Returns all the generic or non-generic methods of the current Type. /// /// True to return all generic methods, false to return all non-generic. /// An array of objects representing all methods /// defined for the current Type. public MethodInfo[] GetMethods(bool generic) { return GetMethods(_type, generic, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } /// /// Returns all the public and non-generic methods of the current Type. /// /// True to return all generic methods, false to return all non-generic. /// An array of objects representing all the public methods /// defined for the current Type. public MethodInfo[] GetPublicMethods(bool generic) { return GetMethods(_type, generic, BindingFlags.Instance | BindingFlags.Public); } /// /// Searches for the generic methods defined for the current Type, /// using the specified binding constraints. /// /// True to return all generic methods, false to return all non-generic. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// An array of objects representing all methods defined /// for the current Type that match the specified binding constraints. public MethodInfo[] GetMethods(bool generic, BindingFlags flags) { return GetMethods(_type, generic, flags); } #endregion #region GetMethod /// /// Searches for the specified instance method (public or non-public), using the specified name. /// /// The String containing the name of the method to get. /// A object representing the method /// that matches the specified name, if found; otherwise, null. public MethodInfo GetMethod(string methodName) { return _type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } /// /// Searches for the specified public instance method, using the specified name. /// /// The String containing the name of the method to get. /// A object representing the method /// that matches the specified name, if found; otherwise, null. public MethodInfo GetPublicMethod(string methodName) { return _type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public); } /// /// Searches for the specified method, using the specified name and binding flags. /// /// The String containing the name of the method to get. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetMethod(string methodName, BindingFlags flags) { return _type.GetMethod(methodName, flags); } /// /// Searches for the specified public instance method, using the specified name. /// /// The String containing the name of the method to get. /// An array of objects representing /// the number, order, and type of the parameters for the method to get.-or- /// An empty array of the type (for example, ) /// to get a method that takes no parameters. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetPublicMethod(string methodName, params Type[] types) { return _type.GetMethod( methodName, BindingFlags.Instance | BindingFlags.Public, null, types, null); } /// /// Searches for the specified instance method (public or non-public), /// using the specified name and argument types. /// /// The String containing the name of the method to get. /// An array of objects representing /// the number, order, and type of the parameters for the method to get.-or- /// An empty array of the type (for example, ) /// to get a method that takes no parameters. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetMethod(string methodName, params Type[] types) { return _type.GetMethod( methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, types, null); } /// /// Searches for the specified method, using the specified name, /// binding flags and argument types. /// /// The String containing the name of the method to get. /// An array of objects representing /// the number, order, and type of the parameters for the method to get.-or- /// An empty array of the type (for example, ) /// to get a method that takes no parameters. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetMethod(string methodName, BindingFlags flags, params Type[] types) { return _type.GetMethod(methodName, flags, null, types, null); } /// /// Searches for the specified instance method (public or non-public), using the specified name. /// /// The String containing the name of the method to get. /// True to search only for a generic method, or /// False to search only for non-generic method. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetMethod(bool generic, string methodName) { return GetMethod(_type, generic, methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } /// /// Searches for the specified public instance method, using the specified name. /// /// The String containing the name of the method to get. /// True to search only for a generic method, or /// False to search only for non-generic method. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetPublicMethod(bool generic, string methodName) { return GetMethod(_type, generic, methodName, BindingFlags.Instance | BindingFlags.Public); } /// /// Searches for the specified method, using the specified name and binding flags. /// /// The String containing the name of the method to get. /// True to search only for a generic method, or /// False to search only for non-generic method. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetMethod(bool generic, string methodName, BindingFlags flags) { return GetMethod(_type, generic, methodName, flags); } /// /// Searches for the specified public instance method, using the specified name and argument types. /// /// The String containing the name of the method to get. /// True to search only for a generic method, or /// False to search only for non-generic method. /// An array of objects representing /// the number, order, and type of the parameters for the method to get.-or- /// An empty array of the type (for example, ) /// to get a method that takes no parameters. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetPublicMethod(bool generic, string methodName, params Type[] types) { return _type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public, generic ? GenericBinder.Generic : GenericBinder.NonGeneric, types, null); } /// /// Searches for the specified instance method (public or non-public), /// using the specified name and argument types. /// /// The String containing the name of the method to get. /// True to search only for a generic method, or /// False to search only for non-generic method. /// An array of objects representing /// the number, order, and type of the parameters for the method to get.-or- /// An empty array of the type (for example, ) /// to get a method that takes no parameters. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetMethod(bool generic, string methodName, params Type[] types) { return _type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, generic ? GenericBinder.Generic : GenericBinder.NonGeneric, types, null); } /// /// Searches for the specified method using the specified name, binding flags and argument types. /// /// The String containing the name of the method to get. /// True to search only for a generic method, or /// False to search only for non-generic method. /// An array of objects representing /// the number, order, and type of the parameters for the method to get.-or- /// An empty array of the type (for example, ) /// to get a method that takes no parameters. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public MethodInfo GetMethod(bool generic, string methodName, BindingFlags flags, params Type[] types) { return _type.GetMethod(methodName, flags, generic ? GenericBinder.Generic : GenericBinder.NonGeneric, types, null); } #endregion #region GetFields /// /// Returns all the public fields of the current Type. /// /// An array of objects representing /// all the public fields defined for the current Type. public FieldInfo[] GetFields() { return _type.GetFields(); } /// /// Searches for the fields of the current Type, using the specified binding constraints. /// /// A bitmask comprised of one or more /// that specify how the search is conducted. /// An array of objects representing /// all fields of the current Type /// that match the specified binding constraints. public FieldInfo[] GetFields(BindingFlags bindingFlags) { return _type.GetFields(bindingFlags); } /// /// Searches for the public field with the specified name. /// /// The String containing the name of the public field to get. /// A object representing the public field with the specified name, /// if found; otherwise, a null reference. public FieldInfo GetField(string name) { return _type.GetField( name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } #endregion #region GetProperties /// /// Returns all the public properties of the current Type. /// /// An array of objects representing /// all public properties of the current Type. public PropertyInfo[] GetProperties() { return _type.GetProperties(); } /// /// Searches for the properties of the current Type, using the specified binding constraints. /// /// A bitmask comprised of one or more /// that specify how the search is conducted. /// An array of objects representing /// all properties of the current Type /// that match the specified binding constraints. public PropertyInfo[] GetProperties(BindingFlags bindingFlags) { return _type.GetProperties(bindingFlags); } /// /// Searches for the public property with the specified name. /// /// The String containing the name of the public property to get. /// A object representing the public property with the specified name, /// if found; otherwise, a null reference. public PropertyInfo GetProperty(string name) { return _type.GetProperty( name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } #endregion #region GetInterfaces /* private Type[] _interfaces; /// /// Gets all the interfaces implemented or inherited by the current . /// /// An array of Type objects representing all the interfaces implemented or /// inherited by the current Type, /// if found; otherwise, an empty array. public Type[] GetInterfaces() { if (_interfaces == null) _interfaces = _type.GetInterfaces(); return _interfaces; } /// /// Gets a specific interface implemented or inherited by the current . /// /// The type of the interface to get. /// A Type object representing the interface of the specified type, if found; /// otherwise, a null reference (Nothing in Visual Basic). public Type GetInterface(Type interfaceType) { foreach (Type intf in GetInterfaces()) if (intf == interfaceType) return null; _type.IsSubclassOf(interfaceType); return null; } */ /// /// Returns an interface mapping for the current . /// /// The /// of the interface of which to retrieve a mapping. /// An object representing the interface /// mapping for . public InterfaceMapping GetInterfaceMap(Type interfaceType) { return _type.GetInterfaceMap(interfaceType); } #endregion #region GetConstructor /// /// Searches for a public instance constructor whose parameters match /// the types in the specified array. /// /// An array of Type objects representing the number, /// order, and type of the parameters for the constructor to get. /// A object representing the /// public instance constructor whose parameters match the types in /// the parameter type array, if found; otherwise, a null reference. public ConstructorInfo GetPublicConstructor(params Type[] types) { return _type.GetConstructor(types); } /// /// Searches for an instance constructor (public or non-public) whose /// parameters match the types in the specified array. /// /// Type object representing type of the /// parameter for the constructor to get. /// A object representing the constructor /// whose parameters match the types in the parameter type array, if found; /// otherwise, a null reference. public ConstructorInfo GetConstructor(Type parameterType) { return GetConstructor(_type, parameterType); } /// /// Searches for an instance constructor (public or non-public) whose /// parameters match the types in the specified array. /// /// An instance of to search constructor for. /// An array of Type objects representing the number, /// order, and type of the parameters for the constructor to get. /// A object representing the constructor /// whose parameters match the types in the parameter type array, if found; /// otherwise, a null reference. public static ConstructorInfo GetConstructor(Type type, params Type[] types) { if (type == null) throw new ArgumentNullException("type"); return type.GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, types, null); } /// /// Searches for a public default constructor. /// /// A object representing the constructor. public ConstructorInfo GetPublicDefaultConstructor() { return _type.GetConstructor(Type.EmptyTypes); } /// /// Searches for a default constructor. /// /// A object representing the constructor. public ConstructorInfo GetDefaultConstructor() { return GetDefaultConstructor(_type); } /// /// Searches for a default constructor. /// /// An instance of to search constructor for. /// A object representing the constructor. public static ConstructorInfo GetDefaultConstructor(Type type) { if (type == null) throw new ArgumentNullException("type"); return type.GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); } /// /// Searches for a public constructors. /// /// An array of objects /// representing all the type public constructors, if found; otherwise, an empty array. public ConstructorInfo[] GetPublicConstructors() { return _type.GetConstructors(); } /// /// Searches for all constructors (except type constructors). /// /// An array of objects /// representing all the type constructors, if found; otherwise, an empty array. public ConstructorInfo[] GetConstructors() { return _type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } #endregion #region Static Members /// /// Gets a value indicating whether a type (or type's element type) /// instance can be null in the underlying data store. /// /// A instance. /// True, if the type parameter is a closed generic nullable type; otherwise, False. /// Arrays of Nullable types are treated as Nullable types. public static bool IsNullable(Type type) { while (type.IsArray) type = type.GetElementType(); return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)); } /// /// Returns the underlying type argument of the specified type. /// /// A instance. /// /// The type argument of the type parameter, /// if the type parameter is a closed generic nullable type. /// The underlying Type if the type parameter is an enum type. /// Otherwise, the type itself. /// /// public static Type GetUnderlyingType(Type type) { if (type == null) throw new ArgumentNullException("type"); if (IsNullable(type)) type = type.GetGenericArguments()[0]; if (type.IsEnum) type = Enum.GetUnderlyingType(type); return type; } /// /// Determines whether the specified types are considered equal. /// /// A instance. /// A type possible derived from the parent type /// True, when an object instance of the type child /// can be used as an object of the type parent; otherwise, false. /// Note that nullable types does not have a parent-child relation to it's underlying type. /// For example, the 'int?' type (nullable int) and the 'int' type /// aren't a parent and it's child. public static bool IsSameOrParent([JetBrains.Annotations.NotNull] Type parent, [JetBrains.Annotations.NotNull] Type child) { if (parent == null) throw new ArgumentNullException("parent"); if (child == null) throw new ArgumentNullException("child"); if (parent == child || child.IsEnum && Enum.GetUnderlyingType(child) == parent || child.IsSubclassOf(parent)) { return true; } if (parent.IsInterface) { Type[] interfaces = child.GetInterfaces(); foreach (Type t in interfaces) if (t == parent) return true; } return false; } public static Type GetGenericType([JetBrains.Annotations.NotNull] Type genericType, Type type) { if (genericType == null) throw new ArgumentNullException("genericType"); while (type != null && type != typeof(object)) { if (type.IsGenericType && type.GetGenericTypeDefinition() == genericType) return type; if (genericType.IsInterface) { foreach (Type interfaceType in type.GetInterfaces()) { Type gType = GetGenericType(genericType, interfaceType); if (gType != null) return gType; } } type = type.BaseType; } return null; } /// /// Searches for the method defined for a , /// using the specified name and binding flags. /// /// The String containing the name of the method to get. /// True to search only for a generic method, or /// False to search only for non-generic method. /// A instance. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public static MethodInfo GetMethod([JetBrains.Annotations.NotNull] Type type, bool generic, string methodName, BindingFlags flags) { if (type == null) throw new ArgumentNullException("type"); foreach (MethodInfo method in type.GetMethods(flags)) { if (method.IsGenericMethodDefinition == generic && method.Name == methodName) return method; } return null; } /// /// Searches for the methods defined for a , /// using the specified name and binding flags. /// /// A instance. /// True to return all generic methods, false to return all non-generic. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// An array of objects representing all methods defined /// for the current Type that match the specified binding constraints. public static MethodInfo[] GetMethods(Type type, bool generic, BindingFlags flags) { if (type == null) throw new ArgumentNullException("type"); return Array.FindAll( type.GetMethods(flags), delegate(MethodInfo method) { return method.IsGenericMethodDefinition == generic; }); } /// /// Searches for the method defined for a , /// using the specified name and binding flags. /// /// A instance. /// The String containing the name of the method to get. /// Number of required (non optional) /// parameter types. /// A bitmask comprised of one or more /// that specify how the search is conducted. /// An array of objects representing /// the number, order, and type of the parameters for the method to get.-or- /// An empty array of the type (for example, ) /// to get a method that takes no parameters. /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public static MethodInfo GetMethod( Type type, string methodName, BindingFlags bindingFlags, int requiredParametersCount, params Type[] parameterTypes) { while (parameterTypes.Length >= requiredParametersCount) { MethodInfo method = type.GetMethod(methodName, parameterTypes); if (null != method) return method; if (parameterTypes.Length == 0) break; Array.Resize(ref parameterTypes, parameterTypes.Length - 1); } return null; } [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] public static object[] GetPropertyParameters(PropertyInfo propertyInfo) { if (propertyInfo == null) throw new ArgumentNullException("propertyInfo"); object[] attrs = propertyInfo.GetCustomAttributes(typeof(ParameterAttribute), true); if (attrs != null && attrs.Length > 0) return ((ParameterAttribute)attrs[0]).Parameters; attrs = propertyInfo.GetCustomAttributes(typeof(InstanceTypeAttribute), true); if (attrs.Length > 0) return ((InstanceTypeAttribute)attrs[0]).Parameters; attrs = new TypeHelper( propertyInfo.DeclaringType).GetAttributes(typeof(GlobalInstanceTypeAttribute)); foreach (GlobalInstanceTypeAttribute attr in attrs) if (IsSameOrParent(attr.PropertyType, propertyInfo.PropertyType)) // if (attr.PropertyType == propertyInfo.PropertyType) return attr.Parameters; return null; } /// /// Searches for the property defined for a , /// using the specified name and parameter types. /// /// A instance. /// The String containing the name of the method to get. /// An array of Type objects representing the number, /// order, and type of the parameters for the constructor to get. /// The property return . /// A object representing the method /// that matches the specified requirements, if found; otherwise, null. public static PropertyInfo GetPropertyInfo( Type type, string propertyName, Type returnType, Type[] types) { if (type == null) throw new ArgumentNullException("type"); return type.GetProperty( propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, returnType, types, null); } /// /// Gets the Type of a list item. /// /// A instance. ///The Type instance that represents the exact runtime type of a list item. public static Type GetListItemType(object list) { Type typeOfObject = typeof(object); if (list == null) return typeOfObject; if (list is EditableArrayList) return ((EditableArrayList)list).ItemType; if (list is Array) return list.GetType().GetElementType(); Type type = list.GetType(); // object[] attrs = type.GetCustomAttributes(typeof(DefaultMemberAttribute), true); // string itemMemberName = (attrs.Length == 0)? "Item": ((DefaultMemberAttribute)attrs[0]).MemberName; if (list is IList || list is ITypedList || list is IListSource) { PropertyInfo last = null; foreach (PropertyInfo pi in type.GetProperties()) { if (pi.GetIndexParameters().Length > 0 && pi.PropertyType != typeOfObject) { if (pi.Name == "Item") return pi.PropertyType; last = pi; } } if (last != null) return last.PropertyType; } try { if (list is IList) { IList l = (IList)list; for (int i = 0; i < l.Count; i++) { object o = l[i]; if (o != null && o.GetType() != typeOfObject) return o.GetType(); } } else if (list is IEnumerable) { foreach (object o in (IEnumerable)list) { if (o != null && o.GetType() != typeOfObject) return o.GetType(); } } } catch { } return typeOfObject; } /// /// Gets the Type of a list item. /// /// A instance. ///The Type instance that represents the exact runtime type of a list item. public static Type GetListItemType(Type listType) { if (listType.IsGenericType) { Type[] elementTypes = GetGenericArguments(listType, typeof(IList)); if (elementTypes != null) return elementTypes[0]; } if (IsSameOrParent(typeof(IList), listType) || IsSameOrParent(typeof(ITypedList), listType) || IsSameOrParent(typeof(IListSource), listType)) { Type elementType = listType.GetElementType(); if (elementType != null) return elementType; PropertyInfo last = null; foreach (PropertyInfo pi in listType.GetProperties()) { if (pi.GetIndexParameters().Length > 0 && pi.PropertyType != typeof(object)) { if (pi.Name == "Item") return pi.PropertyType; last = pi; } } if (last != null) return last.PropertyType; } return typeof(object); } public static Type GetElementType(Type type) { if (type == null) return null; if (type == typeof(object)) return type.HasElementType ? type.GetElementType(): null; if (type.IsArray) type.GetElementType(); if (type.IsGenericType) foreach (Type aType in type.GetGenericArguments()) if (typeof(IEnumerable<>).MakeGenericType(new Type[] { aType }).IsAssignableFrom(type)) return aType; Type[] interfaces = type.GetInterfaces(); if (interfaces != null && interfaces.Length > 0) { foreach (Type iType in interfaces) { Type eType = GetElementType(iType); if (eType != null) return eType; } } return GetElementType(type.BaseType); } /// /// Gets a value indicating whether a type can be used as a db primitive. /// /// A instance. /// True, if the type parameter is a primitive type; otherwise, False. /// . . /// . . are specially handled by the library /// and, therefore, can be treated as scalar types. public static bool IsScalar(Type type) { while (type.IsArray) type = type.GetElementType(); return type.IsValueType || type == typeof(string) || type == typeof(Stream) || type == typeof(XmlReader) || type == typeof(XmlDocument); } /// /// Returns an array of Type objects that represent the type arguments /// of a generic type or the type parameters of a generic type definition. /// /// A instance. ///Non generic base type. ///An array of Type objects that represent the type arguments /// of a generic type. Returns an empty array if the current type is not a generic type. public static Type[] GetGenericArguments(Type type, Type baseType) { string baseTypeName = baseType.Name; for (Type t = type; t != typeof(object) && t != null; t = t.BaseType) if (t.IsGenericType && (baseTypeName == null || t.Name.Split('`')[0] == baseTypeName)) return t.GetGenericArguments(); foreach (Type t in type.GetInterfaces()) if (t.IsGenericType && (baseTypeName == null || t.Name.Split('`')[0] == baseTypeName)) return t.GetGenericArguments(); return null; } /// /// Substitutes the elements of an array of types for the type parameters /// of the current generic type definition and returns a Type object /// representing the resulting constructed type. /// /// A instance. /// An array of types to be substituted for /// the type parameters of the current generic type. /// A Type representing the constructed type formed by substituting /// the elements of for the type parameters /// of the current generic type. /// public static Type TranslateGenericParameters(Type type, Type[] typeArguments) { // 'T paramName' case // if (type.IsGenericParameter) return typeArguments[type.GenericParameterPosition]; // 'List paramName' or something like that. // if (type.IsGenericType && type.ContainsGenericParameters) { Type[] genArgs = type.GetGenericArguments(); for (int i = 0; i < genArgs.Length; ++i) genArgs[i] = TranslateGenericParameters(genArgs[i], typeArguments); return type.GetGenericTypeDefinition().MakeGenericType(genArgs); } // Non-generic type. // return type; } public static bool CompareParameterTypes(Type goal, Type probe) { if (goal == probe) return true; if (goal.IsGenericParameter) return CheckConstraints(goal, probe); if (goal.IsGenericType && probe.IsGenericType) return CompareGenericTypes(goal, probe); return false; } public static bool CheckConstraints(Type goal, Type probe) { Type[] constraints = goal.GetGenericParameterConstraints(); for (int i = 0; i < constraints.Length; i++) if (!constraints[i].IsAssignableFrom(probe)) return false; return true; } public static bool CompareGenericTypes(Type goal, Type probe) { Type[] genArgs = goal.GetGenericArguments(); Type[] specArgs = probe.GetGenericArguments(); bool match = (genArgs.Length == specArgs.Length); for (int i = 0; match && i < genArgs.Length; i++) { if (genArgs[i] == specArgs[i]) continue; if (genArgs[i].IsGenericParameter) match = CheckConstraints(genArgs[i], specArgs[i]); else if (genArgs[i].IsGenericType && specArgs[i].IsGenericType) match = CompareGenericTypes(genArgs[i], specArgs[i]); else match = false; } return match; } public static PropertyInfo GetPropertyByMethod(MethodInfo method) { if (method != null) { Type type = method.DeclaringType; BindingFlags attr = BindingFlags.NonPublic | BindingFlags.Public | (method.IsStatic ? BindingFlags.Static : BindingFlags.Instance); foreach (PropertyInfo info in type.GetProperties(attr)) { if (info.CanRead && method == info.GetGetMethod(true)) return info; if (info.CanWrite && method == info.GetSetMethod(true)) return info; } } return null; } #endregion } }