using System;
using System.Linq;
using System.Threading;
static class Extensions
{
public static Delegate ConvertTo(this Delegate self, Type type)
{
if (type == null) { throw new ArgumentNullException("type"); }
if (self == null) { return null; }
return Delegate.Combine(
self.GetInvocationList()
.Select(i => Delegate.CreateDelegate(type, i.Target, i.Method))
.ToArray());
}
public static T ConvertTo<T>(this Delegate self)
{
return (T)(object)self.ConvertTo(typeof(T));
}
}
public class MyEventArgs : EventArgs { }
public delegate void MyEventHandler(object sender, MyEventArgs e);
public class Foo {
public event EventHandler<MyEventArgs> MyEvent;
public bool IsEventNull() {
return MyEvent == null;
}
}
public class Bar {
public Foo Impl = new Foo();
public event MyEventHandler MyEvent {
add {
Impl.MyEvent += value.ConvertTo<EventHandler<MyEventArgs>>();
}
Impl.MyEvent -= value.ConvertTo<EventHandler<MyEventArgs>>();
}
}
}
public class Baz {
public void MyHandler(object sender, MyEventArgs e) {}
}
class Program
{
static void Main()
{
var bar = new Bar();
var baz = new Baz();
Console.WriteLine("event is null: {0}", bar.Impl.IsEventNull());
bar.MyEvent += baz.MyHandler;
Console.WriteLine("event is null: {0}", bar.Impl.IsEventNull());
bar.MyEvent -= baz.MyHandler;
Console.WriteLine("event is null: {0}", bar.Impl.IsEventNull());
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uTGlucTsKdXNpbmcgU3lzdGVtLlRocmVhZGluZzsKCnN0YXRpYyBjbGFzcyBFeHRlbnNpb25zCnsKCXB1YmxpYyBzdGF0aWMgRGVsZWdhdGUgQ29udmVydFRvKHRoaXMgRGVsZWdhdGUgc2VsZiwgVHlwZSB0eXBlKQoJewoJCWlmICh0eXBlID09IG51bGwpIHsgdGhyb3cgbmV3IEFyZ3VtZW50TnVsbEV4Y2VwdGlvbigidHlwZSIpOyB9CgkJaWYgKHNlbGYgPT0gbnVsbCkgeyByZXR1cm4gbnVsbDsgfQoJCQoJCXJldHVybiBEZWxlZ2F0ZS5Db21iaW5lKAoJCQlzZWxmLkdldEludm9jYXRpb25MaXN0KCkKCQkJCS5TZWxlY3QoaSA9PiBEZWxlZ2F0ZS5DcmVhdGVEZWxlZ2F0ZSh0eXBlLCBpLlRhcmdldCwgaS5NZXRob2QpKQoJCQkJLlRvQXJyYXkoKSk7Cgl9CgkKCXB1YmxpYyBzdGF0aWMgVCBDb252ZXJ0VG88VD4odGhpcyBEZWxlZ2F0ZSBzZWxmKQoJewoJCXJldHVybiAoVCkob2JqZWN0KXNlbGYuQ29udmVydFRvKHR5cGVvZihUKSk7Cgl9Cn0KCnB1YmxpYyBjbGFzcyBNeUV2ZW50QXJncyA6IEV2ZW50QXJncyB7IH0KCnB1YmxpYyBkZWxlZ2F0ZSB2b2lkIE15RXZlbnRIYW5kbGVyKG9iamVjdCBzZW5kZXIsIE15RXZlbnRBcmdzIGUpOwoKcHVibGljIGNsYXNzIEZvbyB7CgpwdWJsaWMgZXZlbnQgRXZlbnRIYW5kbGVyPE15RXZlbnRBcmdzPiBNeUV2ZW50OwoKcHVibGljIGJvb2wgSXNFdmVudE51bGwoKSB7CglyZXR1cm4gTXlFdmVudCA9PSBudWxsOwp9Cgp9CgpwdWJsaWMgY2xhc3MgQmFyIHsKCXB1YmxpYyBGb28gSW1wbCA9IG5ldyBGb28oKTsKCQoJcHVibGljIGV2ZW50IE15RXZlbnRIYW5kbGVyIE15RXZlbnQgewoJCWFkZCB7CgkJCUltcGwuTXlFdmVudCArPSB2YWx1ZS5Db252ZXJ0VG88RXZlbnRIYW5kbGVyPE15RXZlbnRBcmdzPj4oKTsKCQl9IAoJCXJlbW92ZSB7CgkJCUltcGwuTXlFdmVudCAtPSB2YWx1ZS5Db252ZXJ0VG88RXZlbnRIYW5kbGVyPE15RXZlbnRBcmdzPj4oKTsKCQl9Cgl9Cn0KCnB1YmxpYyBjbGFzcyBCYXogewoJcHVibGljIHZvaWQgTXlIYW5kbGVyKG9iamVjdCBzZW5kZXIsIE15RXZlbnRBcmdzIGUpIHt9Cn0KCmNsYXNzIFByb2dyYW0KewoJc3RhdGljIHZvaWQgTWFpbigpCgl7CgkJdmFyIGJhciA9IG5ldyBCYXIoKTsKCQl2YXIgYmF6ID0gbmV3IEJheigpOwoJCQoJCUNvbnNvbGUuV3JpdGVMaW5lKCJldmVudCBpcyBudWxsOiB7MH0iLCBiYXIuSW1wbC5Jc0V2ZW50TnVsbCgpKTsKCQkKCQliYXIuTXlFdmVudCArPSBiYXouTXlIYW5kbGVyOwoJCQoJCUNvbnNvbGUuV3JpdGVMaW5lKCJldmVudCBpcyBudWxsOiB7MH0iLCBiYXIuSW1wbC5Jc0V2ZW50TnVsbCgpKTsKCQkKCQliYXIuTXlFdmVudCAtPSBiYXouTXlIYW5kbGVyOwoJCQoJCUNvbnNvbGUuV3JpdGVMaW5lKCJldmVudCBpcyBudWxsOiB7MH0iLCBiYXIuSW1wbC5Jc0V2ZW50TnVsbCgpKTsKCX0KfQ==