我想编写一个方法来分析任何方法的自定义属性(包含任意数量的参数和任何返回类型),只知道方法信息。
此函数将检查方法是否具有特定属性。像这样:var tmp = methodInfo.GetCustomAttributes(typeof(LineItemAttribute),false);
如果它有这样的属性它将执行它。我希望调用该函数真的很容易使用。因此,在示例中,我想要调用三种方法和方法GetMethodAttributes
。
class Test
{
public static void Main()
{
}
public void Test1(){}
public void Test2(int a){}
public void Test3(object a, string c, Boolean d);
public void GetMethodAttributes(MethodInfo mi) {}
}
理想情况下,我想写类似的东西
public static void Main()
{
var t = new Test();
GetMethodAttributes(t.Test1);
GetMethodAttributes(t.Test2);
GetMethodAttributes(t.Test3);
}
我不想使用方法名称的字符串表示,因为方法名称可能会改变,如:
MethodInfo info = type.GetMethod(name);
我有任何选择吗?基本上我需要一种方法来使用具有不同sinatures的函数的委托
答案 0 :(得分:3)
正如Chris Sinclair在上述评论中指出的那样;您可以使用委托而不使用反射或表达式树来获取MethodInfo
。缺点是编译器无法推断泛型参数,因此您必须指定委托类型以匹配给定方法的签名,如下所示:
public class Test
{
public static void Main()
{
var t = new Test();
CheckMethodAttributes<Action>(t.Test1);
CheckMethodAttributes<Action<int>>(t.Test2);
CheckMethodAttributes<Action<object, string, bool>>(t.Test3);
}
public void Test1() { }
public void Test2(int a) { }
public void Test3(object a, string c, bool d) { }
public static void CheckMethodAttributes<T>(T func)
{
MethodInfo method = new MethodOf<T>(func);
// Example attribute check:
var ignoreAttribute = method.GetAttribute<IgnoreAttribute>();
if (ignoreAttribute != null)
{
// Do something here...
}
}
}
这使用两个实用程序类,MethodOf<T>
用于从给定的MethodInfo
中提取Delegate
,并使用一些AttributeUtils
来获取强类型的自定义属性检索:
public static class AttributeUtils
{
public static bool HasAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.IsDefined(typeof(TAttribute), inherit);
}
public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetAttributes<TAttribute>(inherit).FirstOrDefault();
}
public static IEnumerable<TAttribute> GetAttributes<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetCustomAttributes(typeof(TAttribute), inherit).Cast<TAttribute>();
}
}
public class MethodOf<T>
{
public MethodOf(T func)
{
var del = func as Delegate;
if (del == null) throw new ArgumentException("Cannot convert func to Delegate.", "func");
Method = del.Method;
}
private MethodInfo Method { get; set; }
public static implicit operator MethodOf<T>(T func)
{
return new MethodOf<T>(func);
}
public static implicit operator MethodInfo(MethodOf<T> methodOf)
{
return methodOf.Method;
}
}
答案 1 :(得分:2)
您可以使用Expression Trees执行此类操作,您可以通过lambda表达式传递方法。但是,您仍然需要为参数传递存根值。有关此操作的一个很好的示例,请查看Moq的源代码,该代码广泛使用此模式来设置单元测试的模拟行为。请注意,设置这不是一件小事。如果您需要相对快速和肮脏的东西,最好的选择可能是使用良好的重构工具和/或自动化测试的字符串名称来帮助解决重命名问题。