【问题标题】:Dynamic IL method causes "Operation could destabilize the runtime"动态 IL 方法导致“操作可能会破坏运行时”
【发布时间】:2011-03-16 11:56:23
【问题描述】:

System.Security.VerificationException: 操作可能会破坏稳定 运行。 在 Connance.CommunicatorApi.ReportApiClient.AcknowledgeRecallsAsyncDynamicHandler(对象 , AcknowledgeRecallsCompletedEventArgs )

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

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

我尝试了两种方法:

1) DynamicMethod 是 void 类型 (物体,物体)

2) 类型为 void (object, 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)' 失败。"}

【问题讨论】:

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


    【解决方案1】:

    方法参数为零索引 - 使用 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 方法,该方法为您调用所有已注册的处理程序。

    【讨论】:

    • 我尝试过使用0和1,但是看起来DynamicMethod生成了一个静态方法,所以它只需要两个显式参数而不是3。另外,事件正在正常调用方式。某处有代码(不是我的),它对每个事件都有一个强类型引用并引发它。我只是想插入我的通用处理程序来跟踪这些调用的状态。
    • 如果方法是静态的,那么显式参数从参数索引 0 开始。如果方法是实例,那么“this”指针是参数 0,显式参数从索引 1 开始。动态方法是静态的,所以你需要使用ldarg.0ldarg.1
    • 我编辑了我的问题。事实证明我还有一个问题,因为我在 SL 工作。我确实设法通过使用 DynamicMethod 的安全关键构造函数使其在常规应用程序中工作,该构造函数将它绑定到我正在调用的类的实例(设置所有者的构造函数)。然后我将 3 个 args 传递给它(第一个是隐式 this
    【解决方案2】:

    好的,所以我想出了这个。

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

    那么你就做dm.CreateDelegate(_args_, this)

    【讨论】:

      猜你喜欢
      • 2016-12-06
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 2012-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      相关资源
      最近更新 更多