// **************************************************************** // 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/?p=license&r=2.4. // **************************************************************** using System; using System.Reflection; using System.Collections; namespace NUnit.Core { /// /// Helper methods for inspecting a type by reflection. /// /// Many of these methods take a MemberInfo 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. /// public class Reflect { #region Attributes /// /// Check presence of attribute of a given type on a member. /// /// The member to examine /// The FullName of the attribute type to look for /// True to include inherited attributes /// True if the attribute is present public static bool HasAttribute( MemberInfo member, string attrName, bool inherit ) { object[] attributes = member.GetCustomAttributes( inherit ); foreach( Attribute attribute in attributes ) if ( IsInstanceOfType( attrName, attribute ) ) return true; return false; } /// /// Get attribute of a given type on a member. If multiple attributes /// of a type are present, the first one found is returned. /// /// The member to examine /// The FullName of the attribute type to look for /// True to include inherited attributes /// The attribute or null public static System.Attribute GetAttribute(MemberInfo member, string attrName, bool inherit) { object[] attributes = member.GetCustomAttributes(inherit); foreach (Attribute attribute in attributes) if ( IsInstanceOfType( attrName, attribute ) ) return attribute; return null; } /// /// Get attribute of a given type on an assembly. If multiple attributes /// of a type are present, the first one found is returned. /// /// The assembly to examine /// The FullName of the attribute type to look for /// True to include inherited attributes /// The attribute or null public static System.Attribute GetAttribute(Assembly assembly, string attrName, bool inherit) { object[] attributes = assembly.GetCustomAttributes(inherit); foreach (Attribute attribute in attributes) if ( IsInstanceOfType(attrName, attribute) ) return attribute; return null; } /// /// Get all attributes of a given type on a member. /// /// The member to examine /// The FullName of the attribute type to look for /// True to include inherited attributes /// The attribute or null public static System.Attribute[] GetAttributes( MemberInfo member, string attrName, bool inherit ) { object[] attributes = member.GetCustomAttributes( inherit ); ArrayList result = new ArrayList(); foreach( Attribute attribute in attributes ) if ( IsInstanceOfType( attrName, attribute ) ) result.Add( attribute ); return (System.Attribute[])result.ToArray( typeof( System.Attribute ) ); } /// /// Get all attributes on a member. /// /// The member to examine /// True to include inherited attributes /// The attribute or null public static System.Attribute[] GetAttributes(MemberInfo 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; } /// /// Get all attributes on an assembly. /// /// The assembly to examine /// True to include inherited attributes /// The attributes or null public static System.Attribute[] GetAttributes(Assembly assembly, bool inherit) { object[] attributes = assembly.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 /// /// Check to see if a type implements a named interface. /// /// The type to examine /// The FullName of the interface to check for /// True if the interface is implemented by the type 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 ] /// /// Checks to see if a type inherits from a named type. /// /// The type to examine /// The FullName of the inherited type to look for /// True if the type inherits from the named type. 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 /// /// Find the default constructor on a type /// /// /// public static ConstructorInfo GetConstructor( Type fixtureType ) { return fixtureType.GetConstructor( Type.EmptyTypes ); } /// /// Find the default constructor on a type /// /// /// public static ConstructorInfo GetConstructor( Type fixtureType, Type[] types ) { return fixtureType.GetConstructor( types ); } /// /// Examine a fixture type and return a method having a particular attribute. /// In the case of multiple methods, the first one found is returned. /// /// The type to examine /// The FullName of the attribute to look for /// BindingFlags to use in looking for method /// A MethodInfo or null public static MethodInfo GetMethodWithAttribute( Type fixtureType, string attributeName, BindingFlags bindingFlags, bool inherit ) { foreach(MethodInfo method in fixtureType.GetMethods( bindingFlags ) ) { if( HasAttribute( method, attributeName, inherit ) ) return method; } return null; } /// /// Examine a fixture type and return a count of the methods having a /// particular attribute. /// /// The type to examine /// The FullName of the attribute to look for /// BindingFlags to use in looking for method /// The number of such methods found public static int CountMethodsWithAttribute( Type fixtureType, string attributeName, BindingFlags bindingFlags, bool inherit ) { int count = 0; foreach(MethodInfo method in fixtureType.GetMethods( bindingFlags ) ) { if( HasAttribute( method, attributeName, inherit ) ) count++; } return count; } /// /// Examine a fixture type and get a method with a particular name. /// In the case of overloads, the first one found is returned. /// /// The type to examine /// The name of the method /// BindingFlags to use in the search /// A MethodInfo or null public static MethodInfo GetNamedMethod(Type fixtureType, string methodName, BindingFlags bindingFlags) { foreach (MethodInfo method in fixtureType.GetMethods(bindingFlags)) { if (method.Name == methodName) return method; } return null; } /// /// 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. /// /// The type to examine /// The name of the method /// The full names of the argument types to search for /// BindingFlags to use in the search /// A MethodInfo or null public static MethodInfo GetNamedMethod(Type fixtureType, string methodName, string[] argTypes, BindingFlags bindingFlags) { foreach (MethodInfo method in fixtureType.GetMethods(bindingFlags)) { 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 /// /// Examine a type and return a property having a particular attribute. /// In the case of multiple methods, the first one found is returned. /// /// The type to examine /// The FullName of the attribute to look for /// Binding flags to use in searching /// A PropertyInfo or null public static PropertyInfo GetPropertyWithAttribute( Type fixtureType, string attributeName, BindingFlags bindingFlags ) { foreach(PropertyInfo property in fixtureType.GetProperties( bindingFlags ) ) { if( HasAttribute( property, attributeName, true ) ) return property; } return null; } /// /// Examine a type and get a property with a particular name. /// In the case of overloads, the first one found is returned. /// /// The type to examine /// BindingFlags to use /// A PropertyInfo or null public static PropertyInfo GetNamedProperty( Type type, string name, BindingFlags bindingFlags ) { return type.GetProperty( name, bindingFlags ); } /// /// Get the value of a named property on an object using binding flags of Public and Instance /// /// The object for which the property value is needed /// The name of a non-indexed property of the object /// public static object GetPropertyValue( object obj, string name ) { return GetPropertyValue( obj, name, BindingFlags.Public | BindingFlags.Instance ); } /// /// Get the value of a named property on an object /// /// The object for which the property value is needed /// The name of a non-indexed property of the object /// BindingFlags for use in determining which properties are neededparam> /// 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; } /// /// Set the value of a named property on an object /// /// The object for which the property value is to be set /// The name of a non-indexed property of the object /// The value to which the property is to be set /// BindingFlags for use in determining which properties are neededparam> public static void SetPropertyValue( object obj, string name, object val, BindingFlags bindingFlags ) { PropertyInfo property = GetNamedProperty( obj.GetType(), name, bindingFlags ); if ( property != null ) property.SetValue( obj, val, null ); } #endregion #region Invoke Methods /// /// Invoke the default constructor on a type /// /// The type to be constructed /// An instance of the type public static object Construct( Type type ) { ConstructorInfo ctor = GetConstructor( type ); if ( ctor == null ) throw new InvalidTestFixtureException(type.FullName + " does not have a valid constructor"); return ctor.Invoke( Type.EmptyTypes ); } /// /// Invoke a parameterless method returning void on an object. /// /// A MethodInfo for the method to be invoked /// The object on which to invoke the method public static void InvokeMethod( MethodInfo method, object fixture ) { InvokeMethod( method, fixture, null ); } /// /// Invoke a method returning void, converting any TargetInvocationException /// to an NUnitException /// /// A MethodInfo for the method to be invoked /// The object on which to invoke the method public static void InvokeMethod( MethodInfo method, object fixture, params object[] args ) { if(method != null) { try { method.Invoke( fixture, args ); } catch(TargetInvocationException e) { Exception inner = e.InnerException; throw new NUnitException("Rethrown",inner); } } } #endregion #region Private Constructor for static-only class private Reflect() { } #endregion } }