我如何获得活动的订阅者?

时间:2009-02-21 08:44:11

标签: c# events

我需要将一个事件的订阅者复制到另一个事件。我可以获得一个事件的订阅者(比如MyEvent [0]返回一个委托)吗?

如果无法做到这一点,我会使用add accessor将委托添加到列表中。那会是最好的解决方案吗?

4 个答案:

答案 0 :(得分:29)

C#events / delegates是多播的,因此委托本身是一个列表。在课堂上,为了获得个人来电,您可以使用:

if(field != null) { // or the event-name for field-like events
    // or your own event-type in place of EventHandler
    foreach(EventHandler subscriber in field.GetInvocationList())
    {
        // etc
    }
}

但是,要一次性分配所有内容,只需使用+ =或直接分配:

SomeType other = ...
other.SomeEvent += localEvent;

答案 1 :(得分:13)

如果该事件是由另一个类发布的事件,则不能 - 至少不可靠。虽然我们经常认为事件只是一个委托变量,但它实际上只是一对方法:添加和删除(或订阅和取消订阅)。

如果你自己的代码发布了这个事件,那很简单 - 你可以让添加/删除访问者做任何你喜欢的事情。

查看my article on events并查看是否对您有所帮助。如果没有,请提供有关您想要做的更多详细信息,指定您可以修改哪些代码以及哪些代码无法修改。

答案 2 :(得分:3)

更新(感谢评论者):委托不可用性意味着克隆在任务中无法实现任何目标。

当一个人写道:

myDelegate += AHandler

创建一个全新的委托实例并将其分配给myDelegate。

因此,如果没有克隆调用,下面的代码将完全相同。


MulticastDelegate(基础类型)有一个克隆方法。

为了能够访问底层委托,您可能需要避免使用event关键字生成的常用帮助程序,并直接管理事物(自定义添加和删除访问者)。

显示:

    class Program {
        public delegate void MyDelegate(string name);

        public event MyDelegate EventOne;

        public void HandlerOne(string name) {
            Console.WriteLine("This is handler one: {0}", name);
        }
        public void HandlerTwo(string name) {
            Console.WriteLine("This is handler two: {0}", name);
        }
        public void HandlerThree(string name) {
            Console.WriteLine("This is handler three: {0}", name);
        }

        public void Run() {
            EventOne += HandlerOne;
            EventOne += HandlerTwo;
            Console.WriteLine("Before clone");
            EventOne("EventOne");

            MyDelegate eventTwo = (MyDelegate)EventOne.Clone();
            MyDelegate eventTwo = EventOne;
            Console.WriteLine("After clonecopy");
            EventOne("EventOne");
            eventTwo("eventTwo");

            Console.WriteLine("Change event one to show it is different");
            EventOne += HandlerThree;
            EventOne("EventOne");
            eventTwo("eventTwo");
        }

        static void Main(string[] args) {
            (new Program()).Run();
        }
    }

答案 3 :(得分:3)

如果您需要检查外部类'事件的订阅者:

EventHandler e = typeof(ExternalClass)
    .GetField(nameof(ExternalClass.Event), BindingFlags.Instance | BindingFlags.NonPublic)
    .GetValue(instanceOfExternalClass) as EventHandler;
if (e != null)
{
    Delegate[] subscribers = e.GetInvocationList();
}