我需要将一个事件的订阅者复制到另一个事件。我可以获得一个事件的订阅者(比如MyEvent [0]返回一个委托)吗?
如果无法做到这一点,我会使用add accessor将委托添加到列表中。那会是最好的解决方案吗?
答案 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("Afterclonecopy"); 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();
}