发生通用事件时调用方法
Call a method when a generic event occurs
我在尝试实现对应在 运行 时间内定义的事件激发的方法的调用时遇到问题。我找到了这个答案:
Redirecting to a dynamic method from a generic event handler
并实施了该解决方案,但是当要调用的方法是实例方法而不是静态方法时,我总是遇到异常。
这是我的部分代码:
public class Operation
{
public bool EventFired
{
get { return _eventFired; }
}
private bool _eventFired = false;
public void Execute(object source, string EventName)
{
EventInfo eventInfo = source.GetType().GetEvent(EventName);
Delegate handler = null;
Type delegateHandler = eventInfo.EventHandlerType;
MethodInfo invokeMethod = delegateHandler.GetMethod("Invoke");
ParameterInfo[] parms = invokeMethod.GetParameters();
Type[] parmTypes = new Type[parms.Length];
for (int i = 0; i < parms.Length; i++)
parmTypes[i] = parms[i].ParameterType;
DynamicMethod customMethod = new DynamicMethod
(
"TempMethod",
invokeMethod.ReturnType,
parmTypes,
typeof (Operation).Module
);
MethodInfo inf = typeof (Operation).GetMethod("SetFlag", BindingFlags.Instance | BindingFlags.Public);
ILGenerator ilgen = customMethod.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, inf);
ilgen.Emit(OpCodes.Ret);
//handler = _customMethod.CreateDelegate(delegateHandler); // This works if I change SetFlag() to static
handler = customMethod.CreateDelegate(delegateHandler, this); // I get an ArgumentException at this point:
//Cannot bind to the target method because its signature
//or security transparency is not compatible with that of the delegate type.
eventInfo.AddEventHandler(source, handler);
}
/// <summary>Signals that the event has been raised.</summary>
public void SetFlag()
{
_eventFired = true;
}
}
我找不到摆脱该异常的方法,如果我将 SetFlag() 方法转为静态,代码工作正常,但这不是我需要的。
任何建议将不胜感激。
提前致谢。
我终于通过稍微修改 DynamicMethod 定义解决了这个问题,如这个答案中所述:
Reference 'this' in dynamic event handler
如果我将 class 类型作为第一个值添加到 Type 数组中,然后将其作为参数传递给 DynamicMethod,则委托已正确创建并且它使用实例方法!
public class Operation
{
public bool EventFired
{
get { return _eventFired; }
}
private bool _eventFired = false;
public void Execute(object source, string EventName)
{
EventInfo eventInfo = source.GetType().GetEvent(EventName);
Delegate handler = null;
Type delegateHandler = eventInfo.EventHandlerType;
MethodInfo invokeMethod = delegateHandler.GetMethod("Invoke");
ParameterInfo[] parms = invokeMethod.GetParameters();
Type[] parmTypes = new Type[parms.Length + 1];
parmTypes[0] = this.GetType(); //First parameter is this class type.
for (int i = 0; i < parms.Length; i++)
parmTypes[i + 1] = parms[i].ParameterType;
DynamicMethod customMethod = new DynamicMethod
(
"TempMethod",
invokeMethod.ReturnType,
parmTypes
);
MethodInfo inf = typeof (Operation).GetMethod("SetFlag", BindingFlags.Instance | BindingFlags.Public);
ILGenerator ilgen = customMethod.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, inf);
ilgen.Emit(OpCodes.Ret);
handler = customMethod.CreateDelegate(delegateHandler, this);
eventInfo.AddEventHandler(source, handler);
}
/// <summary>Signals that the event has been raised.</summary>
public void SetFlag()
{
_eventFired = true;
}
}
我在尝试实现对应在 运行 时间内定义的事件激发的方法的调用时遇到问题。我找到了这个答案:
Redirecting to a dynamic method from a generic event handler
并实施了该解决方案,但是当要调用的方法是实例方法而不是静态方法时,我总是遇到异常。 这是我的部分代码:
public class Operation
{
public bool EventFired
{
get { return _eventFired; }
}
private bool _eventFired = false;
public void Execute(object source, string EventName)
{
EventInfo eventInfo = source.GetType().GetEvent(EventName);
Delegate handler = null;
Type delegateHandler = eventInfo.EventHandlerType;
MethodInfo invokeMethod = delegateHandler.GetMethod("Invoke");
ParameterInfo[] parms = invokeMethod.GetParameters();
Type[] parmTypes = new Type[parms.Length];
for (int i = 0; i < parms.Length; i++)
parmTypes[i] = parms[i].ParameterType;
DynamicMethod customMethod = new DynamicMethod
(
"TempMethod",
invokeMethod.ReturnType,
parmTypes,
typeof (Operation).Module
);
MethodInfo inf = typeof (Operation).GetMethod("SetFlag", BindingFlags.Instance | BindingFlags.Public);
ILGenerator ilgen = customMethod.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, inf);
ilgen.Emit(OpCodes.Ret);
//handler = _customMethod.CreateDelegate(delegateHandler); // This works if I change SetFlag() to static
handler = customMethod.CreateDelegate(delegateHandler, this); // I get an ArgumentException at this point:
//Cannot bind to the target method because its signature
//or security transparency is not compatible with that of the delegate type.
eventInfo.AddEventHandler(source, handler);
}
/// <summary>Signals that the event has been raised.</summary>
public void SetFlag()
{
_eventFired = true;
}
}
我找不到摆脱该异常的方法,如果我将 SetFlag() 方法转为静态,代码工作正常,但这不是我需要的。 任何建议将不胜感激。 提前致谢。
我终于通过稍微修改 DynamicMethod 定义解决了这个问题,如这个答案中所述:
Reference 'this' in dynamic event handler
如果我将 class 类型作为第一个值添加到 Type 数组中,然后将其作为参数传递给 DynamicMethod,则委托已正确创建并且它使用实例方法!
public class Operation
{
public bool EventFired
{
get { return _eventFired; }
}
private bool _eventFired = false;
public void Execute(object source, string EventName)
{
EventInfo eventInfo = source.GetType().GetEvent(EventName);
Delegate handler = null;
Type delegateHandler = eventInfo.EventHandlerType;
MethodInfo invokeMethod = delegateHandler.GetMethod("Invoke");
ParameterInfo[] parms = invokeMethod.GetParameters();
Type[] parmTypes = new Type[parms.Length + 1];
parmTypes[0] = this.GetType(); //First parameter is this class type.
for (int i = 0; i < parms.Length; i++)
parmTypes[i + 1] = parms[i].ParameterType;
DynamicMethod customMethod = new DynamicMethod
(
"TempMethod",
invokeMethod.ReturnType,
parmTypes
);
MethodInfo inf = typeof (Operation).GetMethod("SetFlag", BindingFlags.Instance | BindingFlags.Public);
ILGenerator ilgen = customMethod.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, inf);
ilgen.Emit(OpCodes.Ret);
handler = customMethod.CreateDelegate(delegateHandler, this);
eventInfo.AddEventHandler(source, handler);
}
/// <summary>Signals that the event has been raised.</summary>
public void SetFlag()
{
_eventFired = true;
}
}