我有一个带有类的程序集,该类使用委托和自定义事件args定义自定义事件。现在我必须通过我的代码动态加载此程序集并创建此类的实例。直到这里我很好。现在我必须使用自定义委托为类对象引发的事件提供事件处理程序。如何使用Relection为从类引发的事件添加事件处理程序?
答案 0 :(得分:3)
以下是执行此操作的代码:
class Program
{
static void Main(string[] args)
{
// Create publisher.
var pub = Activator.CreateInstance(typeof(Publisher));
// Get the event.
var addEvent = typeof(Publisher).GetEvent("Event");
// Create subscriber.
var sub = Activator.CreateInstance(typeof(Subscriber));
// Get the method.
var handler = typeof(Subscriber).GetMethod("Handle");
// Create a valid delegate for it.
var handlerDelegate = MakeEventHandlerDelegate(handler, sub);
// Add the event.
addEvent.AddEventHandler(pub, handlerDelegate);
// Call the raise method.
var raise = typeof(Publisher).GetMethod("Raise");
raise.Invoke(pub, new object[] { "Test Value" });
Console.ReadLine();
}
static Delegate MakeEventHandlerDelegate(MethodInfo methodInfo, object target)
{
ParameterInfo[] info = methodInfo.GetParameters();
if (info.Length != 2)
throw new ArgumentOutOfRangeException("methodInfo");
if (!typeof(EventArgs).IsAssignableFrom(info[1].ParameterType))
throw new ArgumentOutOfRangeException("methodInfo");
if (info[0].ParameterType != typeof(object))
throw new ArgumentOutOfRangeException("methodInfo");
return Delegate.CreateDelegate(typeof(EventHandler<>).MakeGenericType(info[1].ParameterType), target, methodInfo);
}
}
class Args : EventArgs
{
public string Value { get; set; }
}
class Publisher
{
public event EventHandler<Args> Event;
public void Raise(string value)
{
if (Event != null)
{
Args a = new Args { Value = value };
Event(this, a);
}
}
}
class Subscriber
{
public void Handle(object sender, Args args)
{
Console.WriteLine("Handle called with {0}.", args.Value);
}
}
答案 1 :(得分:1)
事件是一个多播委托,您将检索该事件作为一种System.Delegate使用Delegate.Combine来组合这两个实例,然后将委托设置为组合委托。
C#有一个很好的速记语法:
class SomeClass
{
public event Action<string> TextEvent;
}
你会写这样的东西:(我感觉有点懒,不会检查这个,你必须自己解决问题)
var obj = // instance of SomeClass...
var t = typeof(SomeClass); // you need the type object
var member = t.GetEvent("TextEvent");
member.AddEventHandler(obj, new Action<string>(delegate(string s)){}); // done!
答案 2 :(得分:0)
我以前必须这样做,真的很痛苦 - 最终遇到了这个tutorial。
是否可以在另一个程序集中使用一个接口,以便使用反射来连接事件?只是一个想法...
答案 3 :(得分:0)
我可能遗漏了一些东西,但是如果你知道你需要连接的事件的名称和签名,那么可能你知道暴露该事件的类型。在这种情况下,为什么需要使用反射?只要您具有正确类型的引用,就可以以正常方式附加处理程序。