在发生通用事件时调用方法

时间:2015-12-03 15:13:39

标签: c# events delegates dynamicmethod ilgenerator

我在尝试实现对应该在运行时定义的事件触发的方法的调用时遇到问题。我找到了这个答案:

Redirecting to a dynamic method from a generic event handler

并实现了该解决方案,但是当要调用的方法是实例1而不是静态时,我一直遇到异常。 这是我的部分代码:

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()方法转为静态,代码工作正常,但这不是我需要的。 任何建议将非常感激。 提前致谢。

1 个答案:

答案 0 :(得分:0)

我终于设法通过稍微修改DynamicMethod定义来解决问题,如下面的答案中所述:

Reference 'this' in dynamic event handler

如果我将类类型作为第一个值添加到 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;
    }

}