/src/NUnit/core/Reflect.cs
C# | 443 lines | 230 code | 58 blank | 155 comment | 41 complexity | 73c09540fb921d61459f4297955d1eee MD5 | raw file
Possible License(s): GPL-2.0
- // ****************************************************************
- // This is free software licensed under the NUnit license. You
- // may obtain a copy of the license as well as information regarding
- // copyright ownership at http://nunit.org.
- // ****************************************************************
-
- using System;
- using System.Reflection;
- using System.Collections;
-
- namespace NUnit.Core
- {
- /// <summary>
- /// Helper methods for inspecting a type by reflection.
- ///
- /// Many of these methods take ICustomAttributeProvider as an
- /// argument to avoid duplication, even though certain attributes can
- /// only appear on specific types of members, like MethodInfo or Type.
- ///
- /// In the case where a type is being examined for the presence of
- /// an attribute, interface or named member, the Reflect methods
- /// operate with the full name of the member being sought. This
- /// removes the necessity of the caller having a reference to the
- /// assembly that defines the item being sought and allows the
- /// NUnit core to inspect assemblies that reference an older
- /// version of the NUnit framework.
- /// </summary>
- public class Reflect
- {
- private static readonly BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy;
-
- #region Attributes
-
- /// <summary>
- /// Check presence of attribute of a given type on a member.
- /// </summary>
- /// <param name="member">The member to examine</param>
- /// <param name="attrName">The FullName of the attribute type to look for</param>
- /// <param name="inherit">True to include inherited attributes</param>
- /// <returns>True if the attribute is present</returns>
- public static bool HasAttribute( ICustomAttributeProvider member, string attrName, bool inherit )
- {
- foreach( Attribute attribute in GetAttributes( member, inherit ) )
- if ( IsInstanceOfType( attrName, attribute ) )
- return true;
- return false;
- }
-
- /// <summary>
- /// Get attribute of a given type on a member. If multiple attributes
- /// of a type are present, the first one found is returned.
- /// </summary>
- /// <param name="member">The member to examine</param>
- /// <param name="attrName">The FullName of the attribute type to look for</param>
- /// <param name="inherit">True to include inherited attributes</param>
- /// <returns>The attribute or null</returns>
- public static System.Attribute GetAttribute(ICustomAttributeProvider member, string attrName, bool inherit)
- {
- foreach (Attribute attribute in GetAttributes( member, inherit ) )
- if ( IsInstanceOfType( attrName, attribute ) )
- return attribute;
- return null;
- }
-
- /// <summary>
- /// Get all attributes of a given type on a member.
- /// </summary>
- /// <param name="member">The member to examine</param>
- /// <param name="attrName">The FullName of the attribute type to look for</param>
- /// <param name="inherit">True to include inherited attributes</param>
- /// <returns>The attribute or null</returns>
- public static System.Attribute[] GetAttributes(
- ICustomAttributeProvider member, string attrName, bool inherit)
- {
- ArrayList result = new ArrayList();
- foreach( Attribute attribute in GetAttributes( member, inherit ) )
- if ( IsInstanceOfType( attrName, attribute ) )
- result.Add( attribute );
- return (System.Attribute[])result.ToArray( typeof( System.Attribute ) );
- }
-
- /// <summary>
- /// Get all attributes on a member.
- /// </summary>
- /// <param name="member">The member to examine</param>
- /// <param name="inherit">True to include inherited attributes</param>
- /// <returns>The attribute or null</returns>
- public static System.Attribute[] GetAttributes(
- ICustomAttributeProvider member, bool inherit)
- {
- object[] attributes = member.GetCustomAttributes(inherit);
- System.Attribute[] result = new System.Attribute[attributes.Length];
- int n = 0;
- foreach (Attribute attribute in attributes)
- result[n++] = attribute;
-
- return result;
- }
-
- #endregion
-
- #region Interfaces
-
- /// <summary>
- /// Check to see if a type implements a named interface.
- /// </summary>
- /// <param name="fixtureType">The type to examine</param>
- /// <param name="interfaceName">The FullName of the interface to check for</param>
- /// <returns>True if the interface is implemented by the type</returns>
- public static bool HasInterface( Type fixtureType, string interfaceName )
- {
- foreach( Type type in fixtureType.GetInterfaces() )
- if ( type.FullName == interfaceName )
- return true;
- return false;
- }
-
- #endregion
-
- #region Inheritance
- //SHMARYA: [ 10/12/2005 ]
- /// <summary>
- /// Checks to see if a type inherits from a named type.
- /// </summary>
- /// <param name="type">The type to examine</param>
- /// <param name="parentType">The FullName of the inherited type to look for</param>
- /// <returns>True if the type inherits from the named type.</returns>
- public static bool InheritsFrom( Type type, string typeName )
- {
- for( Type current = type; current != typeof( object ); current = current.BaseType )
- if( current.FullName == typeName )
- return true;
-
- return false;
- }
-
- public static bool InheritsFrom( object obj, string typeName )
- {
- return InheritsFrom( obj.GetType(), typeName );
- }
-
- public static bool IsInstanceOfType( string typeName, Attribute attr )
- {
- Type type = attr.GetType();
- return type.FullName == typeName || InheritsFrom( type, typeName );
- }
- #endregion
-
- #region Get Methods of a type
-
- /// <summary>
- /// Find the default constructor on a type
- /// </summary>
- /// <param name="fixtureType"></param>
- /// <returns></returns>
- public static ConstructorInfo GetConstructor( Type fixtureType )
- {
- return fixtureType.GetConstructor( Type.EmptyTypes );
- }
-
- /// <summary>
- /// Examine a fixture type and return an array of methods having a
- /// particular attribute. The array is order with base methods first.
- /// </summary>
- /// <param name="fixtureType">The type to examine</param>
- /// <param name="attributeName">The FullName of the attribute to look for</param>
- /// <returns>The array of methods found</returns>
- public static MethodInfo[] GetMethodsWithAttribute(Type fixtureType, string attributeName, bool inherit)
- {
- ArrayList list = new ArrayList();
-
- foreach (MethodInfo method in GetMethods(fixtureType))
- {
- if (HasAttribute(method, attributeName, inherit))
- list.Add(method);
- }
-
- list.Sort(new BaseTypesFirstComparer());
-
- return (MethodInfo[])list.ToArray(typeof(MethodInfo));
- }
-
- private static MethodInfo[] GetMethods(Type fixtureType)
- {
- MethodInfo[] result = fixtureType.GetMethods(AllMembers);
-
- return result;
- }
-
- private class BaseTypesFirstComparer : IComparer
- {
- #region IComparer Members
-
- public int Compare(object x, object y)
- {
- MethodInfo m1 = x as MethodInfo;
- MethodInfo m2 = y as MethodInfo;
-
- if (m1 == null || m2 == null) return 0;
-
- Type m1Type = m1.DeclaringType;
- Type m2Type = m2.DeclaringType;
-
- if ( m1Type == m2Type ) return 0;
- if ( m1Type.IsAssignableFrom(m2Type) ) return -1;
-
- return 1;
- }
-
- #endregion
- }
-
- /// <summary>
- /// Examine a fixture type and return true if it has a method with
- /// a particular attribute.
- /// </summary>
- /// <param name="fixtureType">The type to examine</param>
- /// <param name="attributeName">The FullName of the attribute to look for</param>
- /// <returns>True if found, otherwise false</returns>
- public static bool HasMethodWithAttribute(Type fixtureType, string attributeName, bool inherit)
- {
- foreach (MethodInfo method in GetMethods( fixtureType ))
- {
- if (HasAttribute(method, attributeName, inherit))
- return true;
- }
-
- return false;
- }
-
- /// <summary>
- /// Examine a fixture type and get a method with a particular name.
- /// In the case of overloads, the first one found is returned.
- /// </summary>
- /// <param name="fixtureType">The type to examine</param>
- /// <param name="methodName">The name of the method</param>
- /// <returns>A MethodInfo or null</returns>
- public static MethodInfo GetNamedMethod(Type fixtureType, string methodName)
- {
- foreach (MethodInfo method in GetMethods( fixtureType ))
- {
- if (method.Name == methodName)
- return method;
- }
-
- return null;
- }
-
- /// <summary>
- /// Examine a fixture type and get a method with a particular name and list
- /// of arguments. In the case of overloads, the first one found is returned.
- /// </summary>
- /// <param name="fixtureType">The type to examine</param>
- /// <param name="methodName">The name of the method</param>
- /// <param name="argTypes">The full names of the argument types to search for</param>
- /// <returns>A MethodInfo or null</returns>
- public static MethodInfo GetNamedMethod(Type fixtureType, string methodName,
- string[] argTypes)
- {
- foreach (MethodInfo method in GetMethods(fixtureType) )
- {
- if (method.Name == methodName)
- {
- ParameterInfo[] parameters = method.GetParameters();
- if (parameters.Length == argTypes.Length)
- {
- bool match = true;
- for (int i = 0; i < argTypes.Length; i++)
- if (parameters[i].ParameterType.FullName != argTypes[i])
- {
- match = false;
- break;
- }
-
- if (match)
- return method;
- }
- }
- }
-
- return null;
- }
-
- #endregion
-
- #region Get Properties of a type
- /// <summary>
- /// Examine a type and return a property having a particular attribute.
- /// In the case of multiple methods, the first one found is returned.
- /// </summary>
- /// <param name="fixtureType">The type to examine</param>
- /// <param name="attributeName">The FullName of the attribute to look for</param>
- /// <returns>A PropertyInfo or null</returns>
- public static PropertyInfo GetPropertyWithAttribute( Type fixtureType, string attributeName )
- {
- foreach(PropertyInfo property in fixtureType.GetProperties( AllMembers ) )
- {
- if( HasAttribute( property, attributeName, true ) )
- return property;
- }
-
- return null;
- }
-
- /// <summary>
- /// Examine a type and get a property with a particular name.
- /// In the case of overloads, the first one found is returned.
- /// </summary>
- /// <param name="type">The type to examine</param>
- /// <param name="bindingFlags">BindingFlags to use</param>
- /// <returns>A PropertyInfo or null</returns>
- public static PropertyInfo GetNamedProperty( Type type, string name, BindingFlags bindingFlags )
- {
- return type.GetProperty( name, bindingFlags );
- }
-
- /// <summary>
- /// Get the value of a named property on an object using binding flags of Public and Instance
- /// </summary>
- /// <param name="obj">The object for which the property value is needed</param>
- /// <param name="name">The name of a non-indexed property of the object</param>
- /// <returns></returns>
- public static object GetPropertyValue( object obj, string name )
- {
- return GetPropertyValue( obj, name, BindingFlags.Public | BindingFlags.Instance );
- }
-
- /// <summary>
- /// Get the value of a named property on an object
- /// </summary>
- /// <param name="obj">The object for which the property value is needed</param>
- /// <param name="name">The name of a non-indexed property of the object</param>
- /// <param name="bindingFlags">BindingFlags for use in determining which properties are needed</param>param>
- /// <returns></returns>
- public static object GetPropertyValue( object obj, string name, BindingFlags bindingFlags )
- {
- PropertyInfo property = GetNamedProperty( obj.GetType(), name, bindingFlags );
- if ( property != null )
- return property.GetValue( obj, null );
- return null;
- }
- #endregion
-
- #region Invoke Methods
-
- /// <summary>
- /// Invoke the default constructor on a Type
- /// </summary>
- /// <param name="type">The Type to be constructed</param>
- /// <returns>An instance of the Type</returns>
- public static object Construct(Type type)
- {
- ConstructorInfo ctor = GetConstructor(type);
- if (ctor == null)
- throw new InvalidTestFixtureException(type.FullName + " does not have a default constructor");
-
- return ctor.Invoke(null);
- }
-
- /// <summary>
- /// Invoke a constructor on a Type with arguments
- /// </summary>
- /// <param name="type">The Type to be constructed</param>
- /// <param name="arguments">Arguments to the constructor</param>
- /// <returns>An instance of the Type</returns>
- public static object Construct(Type type, object[] arguments)
- {
- if (arguments == null) return Construct(type);
-
- //Type[] argTypes = GetTypeArray(arguments);
- //ConstructorInfo ctor = GetConstructor(type, argTypes);
- //if (ctor == null)
- // throw new InvalidTestFixtureException(type.FullName + " does not have a suitable constructor");
-
- try
- {
- return type.InvokeMember(type.Name, BindingFlags.CreateInstance, null, null, arguments);
- }
- catch (Exception ex)
- {
- throw new InvalidTestFixtureException(type.FullName + " does not have a suitable constructor", ex);
- }
- }
-
- /// <summary>
- /// Returns an array of types from an array of objects.
- /// Used because the compact framework doesn't support
- /// Type.GetTypeArray()
- /// </summary>
- /// <param name="objects">An array of objects</param>
- /// <returns>An array of Types</returns>
- public static Type[] GetTypeArray(object[] objects)
- {
- Type[] types = new Type[objects.Length];
- int index = 0;
- foreach (object o in objects)
- types[index++] = o == null ? null : o.GetType();
- return types;
- }
-
- /// <summary>
- /// Invoke a parameterless method returning void on an object.
- /// </summary>
- /// <param name="method">A MethodInfo for the method to be invoked</param>
- /// <param name="fixture">The object on which to invoke the method</param>
- public static object InvokeMethod( MethodInfo method, object fixture )
- {
- return InvokeMethod( method, fixture, null );
- }
-
- /// <summary>
- /// Invoke a method returning void, converting any TargetInvocationException
- /// to an NUnitException
- /// </summary>
- /// <param name="method">A MethodInfo for the method to be invoked</param>
- /// <param name="fixture">The object on which to invoke the method</param>
- public static object InvokeMethod( MethodInfo method, object fixture, params object[] args )
- {
- if(method != null)
- {
- try
- {
- return method.Invoke( fixture, args );
- }
- catch(TargetInvocationException e)
- {
- Exception inner = e.InnerException;
- throw new NUnitException("Rethrown",inner);
- }
- }
-
- return null;
- }
-
- #endregion
-
- #region Private Constructor for static-only class
-
- private Reflect() { }
-
- #endregion
- }
- }