获取具有属性的静态方法并将它们订阅到一个事件

Get static methods with attribute and subscribe them to an event

如何通过反射获取所有应用了某个属性的静态方法,然后将这些方法订阅到一个事件?

Class通过反射加载的方法:

public static class EventsAndStuff
{
    [DoStuffEvent]
    public static void OnDoStuff(object sender, DoStuffEventArgs e)
    {
        // Do Stuff
    }
}

这里有一个可能会做反射的地方,把事情弄清楚(在main()的开头)

public static class Program
{
    // event to subscribe to
    public static event DoStuffEventHandler DoStuff;

    public static void Main(string[] args)
    {
        // reflection here
    }
}

加载程序启动时,我如何订阅 OnDoStuff() 事件 DoStuffEvent,以便在调用 DoStuffEvent 时调用 OnDoStuff 和任何其他静态方法DoStuffEventAttribute 已应用?

我怀疑这与 MethodInfo.CreateDelegate() 有关,但 MSDN 文档不是特别清楚。

大多数类似问题都涉及将非反射方法订阅到反射加载事件。怎么可能反过来呢?

基本解决方案是循环访问要搜索的程序集中的 类 并测试 类。静态 类 被编译器标记为密封和抽象,因此您需要对此进行测试。然后对于每个方法,检查它是否是静态的以及属性是否存在。然后创建正确类型的委托并将其订阅到事件。

public class SubscriberAttribute : Attribute { }

static class TestClass
{
    [SubscriberAttribute]
    static void Method(object sender, EventArgs args)
    {
        Console.WriteLine("Method called as expected.");
    }

    static void Nonsubscribed(object sender, EventArgs args)
    {
        Console.WriteLine("Wrong method called!");
    }
}

class MethodSubscriber
{
    [STAThread]
    public static void Main()
    {
        var ms = new MethodSubscriber();

        ms.SubscribeToEvent(typeof(MethodSubscriber).Assembly);
    }

    public event EventHandler TestEvent;

    void SubscribeToEvent(Assembly assembly)
    {
        foreach (var type in assembly.GetTypes())
        {
            // Test for a static class
            if (type.IsSealed == false) continue;
            if (type.IsClass == false) continue;

            // Check each method for the attribute.
            foreach (var method in type.GetRuntimeMethods())
            {
                // Make sure the method is static
                if (method.IsStatic == false) continue;

                // Test for presence of the attribute
                var attribute = method.GetCustomAttribute<SubscriberAttribute>();

                if (attribute == null)
                    continue;

                var del = (EventHandler)method.CreateDelegate(typeof(EventHandler));

                TestEvent += del;
            }
        }

        TestEvent(null, EventArgs.Empty);
    }

如果方法的签名与委托类型不匹配,CreateDelegate 方法将抛出异常,因此您可能需要对这种情况进行某种处理。您可以通过反映方法参数并查看它们是否与事件预期的类型匹配来避免异常。