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
}
}