我需要将一个事件的订阅者复制到另一个事件中。我能否获取一个事件的订阅者 (例如 MyEvent[0] 返回一个委托)?
如果无法实现,我将使用 add 访问器将委托添加到列表中。那会是最好的解决方案吗?
C#事件/委托是多路广播的,因此委托本身就是一个列表。从类内部获取单个调用者,您可以使用:
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;
如果您需要检查外部类事件的订阅者:
EventHandler e = typeof(ExternalClass)
.GetField(nameof(ExternalClass.Event), BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(instanceOfExternalClass) as EventHandler;
if (e != null)
{
Delegate[] subscribers = e.GetInvocationList();
}
myDelegate += AHandler
创建一个全新的委托实例并将其分配给myDelegate
。
因此,即使没有Clone调用,下面的代码也会完全相同。
MulticastDelegate
(基础类型)具有Clone
方法。
为了能够获取基础委托,您可能需要避免事件关键字生成的常规帮助程序,并直接管理事物(自定义添加和删除访问器)。
为了展示这一点:
public class Program {
public delegate void MyDelegate(string name);
public event MyDelegate EventOne;
public void HandlerOne(string name) => Console.WriteLine($"This is handler one: {name}");
public void HandlerTwo(string name) => Console.WriteLine($"This is handler two: {name}");
public void HandlerThree(string name) => Console.WriteLine($"This is handler three: {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 clone copy");
EventOne("EventOne");
eventTwo("eventTwo");
Console.WriteLine("Change event one to show it is different");
EventOne += HandlerThree;
EventOne("EventOne");
eventTwo("eventTwo");
}
private static void Main(string[] args) => (new Program()).Run();
}