Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

431 lines
16 KiB
C#

// ****************************************************************
// 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
{
/// <summary>
/// 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.
/// </summary>
public class Reflect
{
#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( MemberInfo member, string attrName, bool inherit )
{
object[] attributes = member.GetCustomAttributes( inherit );
foreach( Attribute attribute in attributes )
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(MemberInfo member, string attrName, bool inherit)
{
object[] attributes = member.GetCustomAttributes(inherit);
foreach (Attribute attribute in attributes)
if ( IsInstanceOfType( attrName, attribute ) )
return attribute;
return null;
}
/// <summary>
/// Get attribute of a given type on an assembly. If multiple attributes
/// of a type are present, the first one found is returned.
/// </summary>
/// <param name="assembly">The assembly 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(Assembly assembly, string attrName, bool inherit)
{
object[] attributes = assembly.GetCustomAttributes(inherit);
foreach (Attribute attribute in attributes)
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( 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 ) );
}
/// <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(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;
}
/// <summary>
/// Get all attributes on an assembly.
/// </summary>
/// <param name="assembly">The assembly to examine</param>
/// <param name="inherit">True to include inherited attributes</param>
/// <returns>The attributes or null</returns>
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
/// <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>
/// Find the default constructor on a type
/// </summary>
/// <param name="fixtureType"></param>
/// <returns></returns>
public static ConstructorInfo GetConstructor( Type fixtureType, Type[] types )
{
return fixtureType.GetConstructor( types );
}
/// <summary>
/// Examine a fixture type and return a method 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>
/// <param name="bindingFlags">BindingFlags to use in looking for method</param>
/// <returns>A MethodInfo or null</returns>
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;
}
/// <summary>
/// Examine a fixture type and return a count of the methods having a
/// particular attribute.
/// </summary>
/// <param name="fixtureType">The type to examine</param>
/// <param name="attributeName">The FullName of the attribute to look for</param>
/// <param name="bindingFlags">BindingFlags to use in looking for method</param>
/// <returns>The number of such methods found</returns>
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;
}
/// <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>
/// <param name="bindingFlags">BindingFlags to use in the search</param>
/// <returns>A MethodInfo or null</returns>
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;
}
/// <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>
/// <param name="bindingFlags">BindingFlags to use in the search</param>
/// <returns>A MethodInfo or null</returns>
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
/// <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>
/// <param name="bindingFlags">Binding flags to use in searching</param>
/// <returns>A PropertyInfo or null</returns>
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;
}
/// <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;
}
/// <summary>
/// Set the value of a named property on an object
/// </summary>
/// <param name="obj">The object for which the property value is to be set</param>
/// <param name="name">The name of a non-indexed property of the object</param>
/// <param name="val">The value to which the property is to be set</param>
/// <param name="bindingFlags">BindingFlags for use in determining which properties are needed</param>param>
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
/// <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 valid constructor");
return ctor.Invoke( Type.EmptyTypes );
}
/// <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 void InvokeMethod( MethodInfo method, object fixture )
{
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 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
}
}