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; }
if (self.GetType() == type)
return self;
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 A { }
public class B : A {}
public delegate void MyEventHandler<in T>(object sender, T arg);
public class TheClass {
public event MyEventHandler<B> MyEvent {
add {
this._myEvent += value.ConvertTo<MyEventHandler<B>>();
}
this._myEvent -= value.ConvertTo<MyEventHandler<B>>();
}
}
private MyEventHandler<B> _myEvent;
public void RaiseEvent(B arg)
{
var handler = this._myEvent;
if(handler != null)
handler(this, arg);
}
}
class Program
{
static void Main()
{
var obj = new TheClass();
obj.MyEvent += new MyEventHandler<B>((sender, e) => Console.WriteLine("B handler: Hey there from {0} with {1}!", sender, e));
obj.MyEvent += new MyEventHandler<A>((sender, e) => Console.WriteLine("A handler: Hey there from {0} with {1}!", sender, e));
obj.MyEvent += new MyEventHandler<object>((sender, e) => Console.WriteLine("Object handler: Hey there from {0} with {1}!", sender, e));
obj.RaiseEvent(new B());
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uTGlucTsKdXNpbmcgU3lzdGVtLlRocmVhZGluZzsKCnN0YXRpYyBjbGFzcyBFeHRlbnNpb25zCnsKCXB1YmxpYyBzdGF0aWMgRGVsZWdhdGUgQ29udmVydFRvKHRoaXMgRGVsZWdhdGUgc2VsZiwgVHlwZSB0eXBlKQoJewoJCWlmICh0eXBlID09IG51bGwpIHsgdGhyb3cgbmV3IEFyZ3VtZW50TnVsbEV4Y2VwdGlvbigidHlwZSIpOyB9CgkJaWYgKHNlbGYgPT0gbnVsbCkgeyByZXR1cm4gbnVsbDsgfQoJCQoJCWlmIChzZWxmLkdldFR5cGUoKSA9PSB0eXBlKQogICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7CiAgICAgICAgICAgICAgICAKCQlyZXR1cm4gRGVsZWdhdGUuQ29tYmluZSgKCQkJc2VsZi5HZXRJbnZvY2F0aW9uTGlzdCgpCgkJCQkuU2VsZWN0KGkgPT4gRGVsZWdhdGUuQ3JlYXRlRGVsZWdhdGUodHlwZSwgaS5UYXJnZXQsIGkuTWV0aG9kKSkKCQkJCS5Ub0FycmF5KCkpOwoJfQoJCglwdWJsaWMgc3RhdGljIFQgQ29udmVydFRvPFQ+KHRoaXMgRGVsZWdhdGUgc2VsZikKCXsKCQlyZXR1cm4gKFQpKG9iamVjdClzZWxmLkNvbnZlcnRUbyh0eXBlb2YoVCkpOwoJfQp9CgpwdWJsaWMgY2xhc3MgQSAgeyB9CgpwdWJsaWMgY2xhc3MgQiA6IEEge30KCnB1YmxpYyBkZWxlZ2F0ZSB2b2lkIE15RXZlbnRIYW5kbGVyPGluIFQ+KG9iamVjdCBzZW5kZXIsIFQgYXJnKTsKCnB1YmxpYyBjbGFzcyBUaGVDbGFzcyB7CiAKIAlwdWJsaWMgZXZlbnQgTXlFdmVudEhhbmRsZXI8Qj4gTXlFdmVudCB7CiAJCWFkZCB7CiAJCQl0aGlzLl9teUV2ZW50ICs9IHZhbHVlLkNvbnZlcnRUbzxNeUV2ZW50SGFuZGxlcjxCPj4oKTsKIAkJfQogCQlyZW1vdmUgewogCQkJdGhpcy5fbXlFdmVudCAtPSB2YWx1ZS5Db252ZXJ0VG88TXlFdmVudEhhbmRsZXI8Qj4+KCk7CiAJCX0KIAl9CiAKCXByaXZhdGUgTXlFdmVudEhhbmRsZXI8Qj4gX215RXZlbnQ7IAoJCglwdWJsaWMgdm9pZCBSYWlzZUV2ZW50KEIgYXJnKQoJewoJCXZhciBoYW5kbGVyID0gdGhpcy5fbXlFdmVudDsKCQlpZihoYW5kbGVyICE9IG51bGwpCgkJCWhhbmRsZXIodGhpcywgYXJnKTsKCX0KIAp9CgpjbGFzcyBQcm9ncmFtCnsKCXN0YXRpYyB2b2lkIE1haW4oKQoJewoJCXZhciBvYmogPSBuZXcgVGhlQ2xhc3MoKTsKCQkKCQlvYmouTXlFdmVudCArPSBuZXcgTXlFdmVudEhhbmRsZXI8Qj4oKHNlbmRlciwgZSkgPT4gQ29uc29sZS5Xcml0ZUxpbmUoIkIgaGFuZGxlcjogSGV5IHRoZXJlIGZyb20gezB9IHdpdGggezF9ISIsIHNlbmRlciwgZSkpOwoJCW9iai5NeUV2ZW50ICs9IG5ldyBNeUV2ZW50SGFuZGxlcjxBPigoc2VuZGVyLCBlKSA9PiBDb25zb2xlLldyaXRlTGluZSgiQSBoYW5kbGVyOiBIZXkgdGhlcmUgZnJvbSB7MH0gd2l0aCB7MX0hIiwgc2VuZGVyLCBlKSk7CgkJb2JqLk15RXZlbnQgKz0gbmV3IE15RXZlbnRIYW5kbGVyPG9iamVjdD4oKHNlbmRlciwgZSkgPT4gQ29uc29sZS5Xcml0ZUxpbmUoIk9iamVjdCBoYW5kbGVyOiBIZXkgdGhlcmUgZnJvbSB7MH0gd2l0aCB7MX0hIiwgc2VuZGVyLCBlKSk7CgkJCgkJb2JqLlJhaXNlRXZlbnQobmV3IEIoKSk7Cgl9Cn0=