有没有办法判断方法是一个事件或属性访问器?

时间:2015-12-28 23:38:14

标签: c# reflection

也就是说,如果MethodInfo检查方法是属性的getter或setter,还是事件的adder或remover或firer(?),而不枚举所有{{1},我怎么能这样做?在包含类型中。编译器是否用一些信息标记这些方法,这些信息可以让我知道我的Property/EventInfos何时是一个?

3 个答案:

答案 0 :(得分:0)

这不是一个完整的解决方案,但是在属性类型不是EventHandler的情况下,你可以通过检查它们的参数和返回值,从事件添加/删除方法中告诉属性get / set方法。

using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;

class Program
{
    static void Main(string[] args)
    {
        foreach (var methodInfo in typeof(TestClass).GetMethods())
        {
            if (!methodInfo.IsSpecialName)
                continue;

            CheckMethod(methodInfo);
        }

        // Method get_Name -> Property Get
        // Method set_Name -> Property Set
        // Method add_NameChanged -> Event Add/Remove
        // Method remove_NameChanged -> Event Add/Remove
    }

    static void CheckMethod(MethodInfo info)
    {
        var parameter = info.GetParameters().FirstOrDefault();
        if (parameter != null)
        {
            if (parameter.ParameterType.BaseType == typeof(MulticastDelegate))
            {
                Trace.WriteLine($"Method {info.Name} -> Event Add/Remove");
            }
            else
            {
                Trace.WriteLine($"Method {info.Name} -> Property Set");
            }
        }
        else if (info.ReturnType != typeof(void))
        {
            Trace.WriteLine($"Method {info.Name} -> Property Get");
        }
    }
}

public class TestClass
{
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name == value)
                return;

            _name = value;
            NameChanged?.Invoke(this, value);
        }
    }
    private string _name;

    public event EventHandler<string> NameChanged;
}

答案 1 :(得分:0)

手动声明的方法与编译器生成的方法之间至少有一个区别是SpecialName对象中存在MethodInfo属性:

要找出与该方法相关联的属性,您需要检查PropertyInfo个对象,以查找相应的GetMethodSetMethod属性,这些属性将链接到这些方法。

示例LINQPad程序:

void Main()
{
    typeof(Test).GetProperties().Select(property => new { property.MetadataToken, property.Name, getter = property.GetMethod?.MetadataToken, setter = property.SetMethod?.MetadataToken }).Dump();
    typeof(Test).GetMethods().Select(method => new { method.MetadataToken, method.Name, IsSpecial = (method.Attributes & MethodAttributes.SpecialName) != 0 }).Dump();
}

public class Test
{
    public int Value
    {
        get;
        set;
    }
}

输出:

enter image description here

答案 2 :(得分:0)

MethodInfo.IsSpecialName对于属性和事件访问器设置为true,对于运算符重载等一些其他特殊方法也是如此。因此,您可以检查此标志并检查参数类型。以下测试程序将输出事件添加/删除访问器:

public class MyEventClass {
private event EventHandler test;
public event EventHandler TestEven {
  add { test += value; }
  remove { test -= value; }
}

}

课程{     static void Main(string [] args)     {

  Type myTestClassType = typeof (MyEventClass);
  var methods = myTestClassType.GetMethods();
  foreach (var methodInfo in methods)
  {
    if (methodInfo.IsSpecialName)
    {
      var parameters = methodInfo.GetParameters();
      if (parameters.Count() == 1 && parameters.ElementAt(0).ParameterType == typeof (EventHandler) &&
          (methodInfo.Name.Contains("add") || methodInfo.Name.Contains("remove")))
      {
        Console.WriteLine(methodInfo.Name);
      }

    }
  }

}

}