this.DataBindings.Add(new Binding("Text", brain, "Dump"));

Development and .Net

  Home  |   Contact  |   Syndication    |   Login
  5 Posts | 0 Stories | 11 Comments | 4 Trackbacks

News

Archives

Post Categories

.Net Development

test Recently I had one of those aggrivating, head pounding, pick up the monitor and throw it through the window, wall, co-worker, whatever is closest.  The issue involved using DynamicMethods, CreateDelegate method, and binding the DynamicMethod to an object.  I was working on an experiment with DynamicMethods and Generics (thats for another post), when I encountered the problem.  Thinking it was some issue to do with the Generics (which there are a lot), I worked on a test code that had nothing to do with Generics and still ran into the problem.

Now according to the .Net documentation the first parameter of the DynamicMethod, when used in CreateDelegate bound to an object, has to be the same type as the object  to which the method is being bound.  
Parameters for overloaded CreateDelegate method of DynamicMethod:
    delegateType
   
A delegate type whose signature matches that of the dynamic method, minus the first parameter.

    target
   
An object the delegate is bound to. Must be of the same type as the first parameter of the dynamic method.

Now here is code similar to what i was working on.

    public delegate void TestingDelegate(Form instance, int value);

    
public class BadGenerator
    {
        
public Delegate Generate(Form instance)
        {
            
Type[] parameters = new Type[2];
            parameters[0] =
typeof(Form);
            parameters[1] =
typeof(int);

            
DynamicMethod dm = new DynamicMethod("", typeof(void), parameters, typeof(Form));
            
ILGenerator il = dm.GetILGenerator();
            
            il.Emit(
OpCodes.Ret);

            
return dm.CreateDelegate(typeof(TestingDelegate), instance);
        }
    }


Now I imagine that some of the more observent of you have already noticed my simple but stupid mistake.  Whenever I ran ithis code, it would throw an exception when it tries to execute the CreateDelegate function.  It would always throw System.ArgumentException "Error binding to target method."  Not exactly the most descriptive error message.  I tiried lots of things to get it to work, even used Reflector to trace the calls (no luck, it ends up calling some Win32 APIs).  I spent too much time trying to figure this problem out, without any luck.  Then I happened to be rereading the documentation, for the tenth time it seemed, when I saw this in the Remarks about the CreateDelegate function:

This method overload requires target to be of the same type as the first parameter of the dynamic method, or to be assignable to that type (for example, a derived class). The signature of delegateType has all the parameters of the dynamic method except the first. For example, if the dynamic method has the parameters String, Int32, and Byte, then delegateType has the parameters Int32 and Byte; target is of type String.

I've bolded the most important sentence.  When I read that, I felt like an idiot, a very very very big idiot.
The corrected code would be:

    public delegate void TestingDelegate(int value);

    
public class BadGenerator
    {
        
public Delegate Generate(Form instance)
        {
            
Type[] parameters = new Type[2];
            parameters[0] =
typeof(Form);
            parameters[1] =
typeof(int);

            
DynamicMethod dm = new DynamicMethod("", typeof(void), parameters, typeof(Form));
            
ILGenerator il = dm.GetILGenerator();
            
            il.Emit(
OpCodes.Ret);

            
return dm.CreateDelegate(typeof(TestingDelegate), instance);
        }
    }

I had to change the delegate from ( public delegate void TestingDelegate(Form instance, int value); ) to ( public delegate void TestingDelegate(int value); ), because a DynamicMethod bound to an object always takes one more parameter than the delegate it is referencing.  The other solution would be to define another parameter for the DynamicMethod, so the parameter list would be (Form, Form, int).

So what is the moral of the story:

Always Read The Documentation, Completely.
posted on Friday, March 17, 2006 2:18 PM

Feedback

# re: DynamicMethods and the Importance of Reading Documentation 8/31/2007 6:42 AM learnerplates
Kraki,
I've spent a couple of weeks now at this DynamicMethod and it's CreateDelegate myself. I sympathize I came across similar problems myself, even after a couple of weeks playing with it on and off it still can confuse me at times, especially since you only seem to get the one Exception no matter what you break.

One spot of confusion for me is how the instance is stored in the Delegate! Is a copy of the instance made and stored in the Delegate code?
I've played around with it and found that setting the original instance to Null after the Delegate has been created makes no difference to the Invokation of the delegate.

I came across these issues when Dumping the DynamicMethods out to an Assembly. When I read the Methods back in from the Assembly into a DynamicMethod and then try to invoke in the same manner as with the CreateDelagate it fails I presume it's because the instance is required to still live in memory somewhere!
Can you help?

Cheers,
LP.

Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: