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

发布于 2024-10-22 12:50:59 字数 3182 浏览 0 评论 0原文

系统安全性验证异常: 操作可能会破坏稳定 运行时。 在Connance.CommunicatorApi.ReportApiClient.AcknowledgeRecallsAsyncDynamicHandler(对象 、AcknowledgeRecallsCompletedEventArgs )

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

我决定尝试一些事情。如果事件是 EventHandler,我仍然可以注册签名 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 设为公共静态并加载参数 0-1?我最终收到这样的错误:

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

System.Security.VerificationException:
Operation could destabilize the
runtime.
at Connance.CommunicatorApi.ReportApiClient.AcknowledgeRecallsAsyncDynamicHandler(Object
, AcknowledgeRecallsCompletedEventArgs
)

That's the error I'm getting. What I'm trying to do (background) is create a global event handler for a class of methods. I'm working with a Static Proxy in WCF and I need to create a layer which tracks all the calls and returns to all of the WCF web methods. Unfortunately, WCF strongly types the "Completed" events' EventArgs, making it nearly impossible.

I decided to try something. If an event is EventHandler<SomeSpecificEventArgs>, I can still register a method of signature void Method(object, object) to handle the event. Great. So I set off to create a DynamicMethod which would call my global handler, and register it to each event.

I tried two ways:

1) DynamicMethod is of type void
(object, object)

2) of type void (object,
SomeSpecificEventArgs) -- I use a
generic method for this to get the
type.

Only, when I try to invoke the method, either manually or for the event, I get the above exception.

Here's my code:

    // 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);
}

edit:
I see. It turns out I have another issue. I'm working in Silverlight. I managed to reproduce my scenario in a separate project and I got it working by using the overload of DynamicMethod which allows you to set an owner. I then specify

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

and use ldarg.0, ldarg.1, and ldarg.2. But this is a security critical constructor and won't run on silverlight. I'm just not sure how I need to set it up then. Do I make the Handler public static and load args 0-1? I end up getting an error like this:

Attempt by method
'DynamicClass.TestMethod2(System.String,
System.String)' to access method
'dynamicass.MyClass.Handler(System.String,
System.String)' failed."}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萝莉病 2024-10-29 12:50:59

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

Method arguments are zero indexed - use ldarg.0 and ldarg.1 instead of ldarg.1 and ldarg.2

Theres also a problem with calling the event handler method - you're not specifying the this pointer for the method (Delegate.Target). You need to provide a this pointer, which may or may not be static depending on what is registered.

This also doesn't take care of multicast delegates - this would only call one of the handlers registered on the event. What you need to do is produce a method something like 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
}

This uses the event's Invoke method, which deals with calling all the registered handlers for you.

哎呦我呸! 2024-10-29 12:50:59

好吧,所以我想到的就是这个。

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

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

Ok, so what I came up was with this.

Make the Handler method an instance method, and add another argument type for the DynamicMethod constructor of the type of the class that owns it (for the implicit this argument).

then you do dm.CreateDelegate(_args_, this)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文