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