Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何动态订阅事件?_C#_.net_Reflection - Fatal编程技术网

C# 如何动态订阅事件?

C# 如何动态订阅事件?,c#,.net,reflection,C#,.net,Reflection,相关的 我需要检测何时触发事件。为此,我正在尝试动态订阅该事件 问题是我有不同类型的委托,不是所有事件都有相同的签名。提供的解决方案需要对象发送方EventArgs e,我没有使用它,因此我得到一个异常,告诉我类型不匹配 以下是我的代表的一些例子: public delegate void OnEventA(int id); public delegate void OnEventB(double num, string name); 如何创建正确的代理?EventInfo有一个方法可

相关的


我需要检测何时触发事件。为此,我正在尝试动态订阅该事件

问题是我有不同类型的委托,不是所有事件都有相同的签名。提供的解决方案需要
对象发送方EventArgs e
,我没有使用它,因此我得到一个异常,告诉我类型不匹配

以下是我的代表的一些例子:

public delegate void OnEventA(int id);
public delegate void OnEventB(double num, string name);

如何创建正确的代理?

EventInfo
有一个方法可以使用。如果没有委托实例,则可以使用
delegate.CreateDelegate
动态创建委托:

var eh = Delegate.CreateDelegate(ei.EventHandlerType, target, methodInfo);
ei.AddEventHandler(owner, eh);

在此示例中,
target
是代理的目标对象,
methodInfo
target
对象中方法的
methodInfo
。最后,
owner
是事件
ei
所属的对象。

经过一些研究,我发现了一些文章:

它帮助我明白我在努力做什么,我应该做什么

我需要使用
Delegate.CreateDelegate
传递
EventHandlerType
(事件的类型,委托)、类的实例以及将处理事件的方法(来自上一个参数中的类)的方法信息。目标是触发此事件的控件

Delegate handler = Delegate.CreateDelegate(evt.EventHandlerType, abc, mi1, false);
evt.AddEventHandler(target, handler);
进一步的挖掘使我找到了这种方法。我可以使用lambda表达式订阅事件。使用我可以订阅不同类型和数量的参数

public static Delegate Create<T>(EventInfo e, Action<T> a)
{
    var parameters = e.EventHandlerType.GetMethod("Invoke").GetParameters().Select(p => Expression.Parameter(p.ParameterType, "p")).ToArray();
    var exp = Expression.Call(Expression.Constant(a), a.GetType().GetMethod("Invoke"), parameters);
    var l = Expression.Lambda(exp, parameters);
    return Delegate.CreateDelegate(e.EventHandlerType, l.Compile(), "Invoke", false);
}
公共静态委托创建(事件信息e,操作a)
{
var parameters=e.EventHandlerType.GetMethod(“调用”).GetParameters().Select(p=>Expression.Parameter(p.ParameterType,“p”)).ToArray();
var exp=Expression.Call(Expression.Constant(a),a.GetType().GetMethod(“Invoke”),参数);
var l=表达式.Lambda(exp,参数);
返回Delegate.CreateDelegate(e.EventHandlerType,l.Compile(),“Invoke”,false);
}
使用此方法(e是EventInfo;EventManager是具有上述静态方法的类)

e.AddEventHandler(这是EventManager.Create(e,(x)=>Console.WriteLine(“执行”));

我需要MethodInfo吗?我不能用lambda吗?如果我需要传递参数怎么办?@BrunoLM:如果您知道委托类型(例如
EventHandler
),可以使用lambda代替
eh
)。如果您不知道这一点,您将需要创建某个(您的)对象的新实例,使用它代替
target
,并在构造函数中将参数传递给此对象(在这种情况下,方法信息将是关于此对象中某个方法的信息-例如,您可以定义
调用
方法)。更具体地说:您可以尝试
OnLoad eh=()=>{…}
。只要所有可勾选的
事件都是委托类型
OnLoad
,它就可以工作。如果委托在每种情况下都不同怎么办?如果它有参数呢?如果代理不同,则需要使用
CreateDelegate
动态创建它。要提供一些参数,您需要创建一个新对象来代替
target
e.AddEventHandler(this, EventManager.Create<int>(e, (x) => Console.WriteLine("Execute")));