我可以从通用委托获取方法属性吗?
我确定论坛上已经有答案了,但到目前为止我还没有找到答案。按照this example我使用匿名方法连同代表以有不同的参数,但相同的返回类型作为一切工作的函数参数不同的方法:我可以从通用委托获取方法属性吗?
public delegate TestCaseResult Action();
...
[TestDescription("Test whether the target computer has teaming configured")]
public TestCaseResult TargetHasOneTeam()
{
// do some logic here and return
// TestCaseResult
}
[TestDescription("Test whether the target computer has the named team configured")]
public TestCaseResult TargetHasNamedTeam(string teamName)
{
// do some logic here and return
// TestCaseResult
}
...
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
// I want to get the value of the TestDescription attribute here
}
...
// usage
TestThat(() => TargetHasOneTeam());
TestThat(() => TargetHasNamedTeam("Adapter5"));
正如你看到的例子,我'真的很想能够从TestThat()函数中获取TestDescriptionAttribute属性。我已经通过Action参数包含了我的方法,但一直未能“找到”我的TargetHasOneTeam()方法。
如果你改变TestThat(() => TargetHasOneTeam())
(你包装一下你的委托到另一个动作)来TestThat(TargetHasOneTeam)和改变TestThat这样的:
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
var attrs = action.GetInvocationList()[0].Method.GetCustomAttributes(true);
// I want to get the value of the TestDescription attribute here
}
会给你你所需要的。
随着表达式:
public static void TestThat(Expression<Func<TestResult>> action)
{
var attrs = ((MethodCallExpression)action.Body).Method.GetCustomAttributes(true);
var result = action.Compile()();
}
我明白如何做到这一点,如果TargetHasOneTeam ()没有参数,但是如果我还想用另一个函数做这个,比如说CheckTargetTeamName(string name)? – millejos
然后将您的TestThat(...)更改为TestThat(表达式
在这种特殊情况下,它本质上是无法访问的。您正在创建一个执行相关方法的lambda表达式。该lambda最终导致生成一个新方法,最终是Action
委托人的参数。该方法与TargetHasOneTeam
没有任何关系,只有在您深入了解正文中的IL指令时才显然。
您可以跳过lambda并在此处执行方法组转换。
TestThat(TargetHasOneTeam);
现在TargetHasOneTeam
被直接分配给委托实例,并会在Delegate::MethodInfo
属性可见。
注:一般来说,虽然这是一个坏主意,正是你遇到的问题。方法上的属性不应该影响它满足委托实例化的能力。如果可能的话,我会避免这种类型的检查。
瓦尔解释了如何做,但我想我同意你的看法,这似乎不是一个好主意,谢谢你对幕后发生的事情的解释。 – millejos
您可以通过Attribute.GetCustomAttribute
获得任何成员的属性。首先检查属性是否定义。例如:
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
if(System.Attribute.IsDefined(action.Method, typeof(TestDescriptionAttribute)))
{
var attribute = (TestDescriptionAttribute)System.Attribute.GetCustomAttribute(action.Method,
typeof(TestDescriptionAttribute));
Console.WriteLine(attribute.TestDescription);
}
}
它将如何帮助获取从委托的* inside *中调用的方法的属性? –
在我的示例中添加了一些细节;它没有被执行*从一个委托内* –
我认为这个例子可以工作,如果我没有用匿名方法包装我的方法调用。(如果我使用下面的Val Bakhtin的例子,而不是我目前正在做的) – millejos
查看MSDN这个例子。
class TestAuthorAttribute
{
static void Test()
{
PrintAuthorInfo(typeof(FirstClass));
PrintAuthorInfo(typeof(SecondClass));
PrintAuthorInfo(typeof(ThirdClass));
}
private static void PrintAuthorInfo(System.Type t)
{
System.Console.WriteLine("Author information for {0}", t);
// Using reflection.
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // Reflection.
// Displaying output.
foreach (System.Attribute attr in attrs)
{
if (attr is Author)
{
Author a = (Author)attr;
System.Console.WriteLine(" {0}, version {1:f}", a.GetName(), a.version);
}
}
}
我认为这是唯一可能的,如果你使用一个表达式例如。 'System.Linq.Expressions.Expression'。然后,您可以将主体转换为MethodCallExpression,并使用里面的MethodInfo对象来查询属性... –
MattDavey
您的委托变成编译器生成的类,派生自类似于MulticastDelegate这样的包含您的方法信息的类。我认为有可能用反思来得到它。 –
我已经在类似的情况下对这种模式进行了尝试。我发现它非常脆弱。仅供参考。 – usr