我可以从泛型委托中获取方法属性吗?

时间:2012-05-14 22:48:32

标签: c# reflection delegates attributes

我确定论坛上已有答案,但到目前为止我还没有找到答案。根据{{​​3}}我将匿名方法与委托结合使用,以便使用不同参数的不同方法,但相同的返回类型都可以作为函数参数使用:

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()方法。

4 个答案:

答案 0 :(得分:4)

在这种特殊情况下,它基本上是无法访问的。您正在创建一个执行相关方法的lambda。该lambda最终会生成一个新方法,最终成为Action委托的参数。该方法与TargetHasOneTeam没有关系,只是在你深入了解体内的IL指令时才显然。

您可以跳过lambda并在此处执行方法组转换。

TestThat(TargetHasOneTeam);

现在TargetHasOneTeam被直接分配给委托实例,并且在Delegate::MethodInfo属性中可见。

注意:一般情况下,这对于您遇到的问题确实是一个坏主意。方法上的属性不应影响它满足委托实例化的能力。如果可能的话,我会避免这种检查。

答案 1 :(得分:3)

如果您将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()();
}

答案 2 :(得分:1)

您可以使用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);
    }
}

答案 3 :(得分:0)

请参阅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);
        }
      }
  }