The Dynamic IL method calls "Operation can destabilize runtime"

System.Security.VerificationException: Operation may destabilize at runtime. in Connance.CommunicatorApi.ReportApiClient.AcknowledgeRecallsAsyncDynamicHandler (object, AcknowledgeRecallsCompletedEventArgs)

This is the error I am getting. What I'm trying to do (background) is to create a global event handler for the class of methods. I am working with a static proxy in WCF, and I need to create a layer that tracks all calls and returns all WCF web methods. Unfortunately, WCF strongly calls EventArgs events “Completed,” which makes it virtually impossible.

I decided to try something. If the EventHandler<SomeSpecificEventArgs> event, I can still register the void Method(object, object) signature method to handle the event. Excellent. So I went to create a DynamicMethod that my global handler would call and register it for each event.

I tried two ways:

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

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

Only when I try to call a method, either manually or for an event, do I get the exception above.

Here is 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 understand. Turns out I have another problem. I work in Silverlight. I managed to reproduce my script in a separate project, and I got it using DynamicMethod overload, which allows you to set the owner. Then i point

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 critical security constructor and will not work on Silverlight. I just don’t know how I need to configure this. Am I doing Handler public static and load args 0-1? I get an error message:

An attempt using the method "DynamicClass.TestMethod2 (System.String, System.String) 'to access the method" Dynamicass.MyClass.Handler (System.String, System.String)' failed. "}

+4
source share
2 answers

Okay, so I came with this.

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

then you do dm.CreateDelegate(_args_, this)

0
source

method arguments null are indexed - use ldarg.0 and ldarg.1 instead of ldarg.1 and ldarg.2

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

It also does not care about multicast delegates - it will only call one of the handlers registered in the event. What you need to do is create a method similar to 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 } 

It uses the event Invoke method, which is designed to call all the handlers you registered.

+4
source

Source: https://habr.com/ru/post/1343909/


All Articles