动态IL方法导致“操作可能破坏运行时的稳定性”

时间:2011-03-16 11:56:24

标签: c# wcf c#-4.0 il dynamicmethod

  

System.Security.VerificationException:   行动可能破坏稳定   运行。          在Connance.CommunicatorApi.ReportApiClient.AcknowledgeRecallsAsyncDynamicHandler(Object   ,AcknowledgeRecallsCompletedEventArgs   )

这就是我得到的错误。我正在尝试做的(背景)是为一类方法创建一个全局事件处理程序。我正在使用WCF中的静态代理,我需要创建一个跟踪所有调用并返回所有WCF Web方法的层。不幸的是,WCF强烈地键入了“已完成”事件的EventArgs,几乎不可能。

我决定尝试一下。如果事件是EventHandler<SomeSpecificEventArgs>,我仍然可以注册签名方法void Method(object, object)来处理事件。大。所以我开始创建一个DynamicMethod来调用我的全局处理程序,并将其注册到每个事件。

我尝试了两种方法:

  

1)DynamicMethod的类型为void   (对象,对象)

     

2)类型为void(对象,   SomeSpecificEventArgs) - 我用的是   通用的方法来获得   类型。

只有当我尝试手动或为事件调用方法时,我才会得到上述异常。

这是我的代码:

    // The handler for all callbacks.
// in the example it does nothing.
public void Handler(object sender, object e)
{
    dynamic evtArgs = e;
    object userState = evtArgs.UserState;
}

private string GetIdentifier(Delegate d)
{
    return string.Concat(d.Method.DeclaringType, '.', d.Method.Name);
}

// Method to register an event handler
public void Register<T> (Delegate o) where T : EventArgs
{
    // get some info
    /* snip. code to get method name, and calculate name of event */

    var eventInst = ownerType.GetEvent(eventName);

    // The following works, for example:
    // someObj.MethodCompleted += Handler;
    // even though MethodCompleted is an event of type EventHandler<SomeSpecialEventArgs>

    // get the actual type of handler
    var handlerType = eventInst.EventHandlerType;
    EventHandler evtHandler = new EventHandler(Handler);    

    DynamicMethod dm = new DynamicMethod(
        GetIdentifier(o) + "DynamicHandler", // set the name
        typeof(void),                        // return void
        new[] { typeof(object), typeof(T) });// params object and type of event args

    ILGenerator gen = dm.GetILGenerator();

    gen.Emit(OpCodes.Ldarg_0); // load first arg to stack for calling
    gen.Emit(OpCodes.Ldarg_2); // load second arg to stack for calling

    gen.Emit(OpCodes.Call, evtHandler.Method); // call method

    gen.Emit(OpCodes.Ret); // return

    // this is the final delegate
    var superdlg = dm.CreateDelegate(handlerType);

    // the problem beings here:
    // when the event is raised and the delegate is invoked
    // of if I dynamicInvoke it, I get the error
    eventInst.AddEventHandler(ownerInst, superdlg);
}

编辑: 我知道了。事实证明我有另一个问题。我在Silverlight工作。我设法在一个单独的项目中重现我的场景,并通过使用允许您设置所有者的DynamicMethod重载来实现它。然后我指定

DynamicMethod dm = new DynamicMethod("TestMethod2", typeof(void), new[] { typeof(MyClass), typeof(string), typeof(string) }, typeof(MyClass));

并使用ldarg.0ldarg.1ldarg.2。但这是一个安全关键的构造函数,不会在Silverlight上运行。我只是不确定我需要如何设置它。我是否使Handler公共静态并加载args 0-1?我最终得到这样的错误:

  

尝试方法   “DynamicClass.TestMethod2(System.String,   System.String)'来访问方法   “dynamicass.MyClass.Handler(System.String,   System.String)'失败。“}

2 个答案:

答案 0 :(得分:4)

方法参数为零索引 - 使用ldarg.0ldarg.1代替ldarg.1ldarg.2

还有一个问题是调用事件处理程序方法 - 您没有为方法指定this指针(Delegate.Target)。您需要提供一个this指针,根据注册的内容,该指针可能是静态的,也可能不是静态的。

这也不会处理多播委托 - 这只会调用在事件上注册的处理程序之一。你需要做的是产生这样的方法:

.method public static CallEventHandler(EventHandlerType ev, object sender, EventArgsType e) {
    ldarg.0   // the Invoke 'this' pointer
    ldarg.1
    ldarg.2
    callvirt instance void EventHandlerType::Invoke(object, EventArgsType)
    ret
}

这使用事件的Invoke方法,该方法处理为您调用所有注册的处理程序。

答案 1 :(得分:0)

好的,所以我提出的就是这个。

使Handler方法成为实例方法,并为拥有它的类的类型DynamicMethod构造函数添加另一个参数类型(对于隐式this参数)。< / p>

然后你做dm.CreateDelegate(_args_, this)