4

I am loading a dll using loadfrom and iterating thru the methods to find ones that match a signature. When I find it I want to assign it as a delegate so I can call it later. This is what I am doing...

foreach (MethodInfo method in methodInfos)
{
    if (method.GetParameters().Length == 2)
    {
        ParameterInfo[] parameters = method.GetParameters();
        if (parameters[0].ParameterType.Name == "Command" 
            && parameters[1].ParameterType.Name == "ExposedVariables")
        {
            aoc.methodinfo = method;
            Command.delCmdMethod del = (Command.delCmdMethod) 
                            Delegate.CreateDelegate(typeof(Command.delCmdMethod)
                                                   , null
                                                   , method);
        } 
     }
}

Problem is - the delegate assignment does not work. I get an error binding to target method.

I read on the web that the the 2nd parameter could be the issue if the method is not static. My method is NOT static.

Any ideas?

Steven Jeuris
  • 18,274
  • 9
  • 70
  • 161
Jeff
  • 53
  • 1
  • 4

2 Answers2

2

Although Miky Dinescu's answer might be helpful, it is only partially correct. There does exist an overload for Delegate.CreateDelegate which will most likely help you.

First off, Miky is right that you have to pass the instance as the second parameter, but this is only the case if you want to create what is called a closed delegate. This means an instance is bound to the delegate along with the method. In practice this means when calling the delegate, it will always operate on the same instance.

From your question, it looks like that isn't what you are trying to achieve. If you want to be able to pass the instance along when calling the delegate, you have to use the CreateDelegate( Type type, MethodInfo method ) overload. This allows you to create what is called an open instance delegate.

Since you'll have to pass the instance along when calling the method, this means there is an extra parameter required in your delegate type. The first parameter of your delegate type will need to correspond to the type of the class in which the method is contained.

Example:

MethodInfo toUpperMethod
    = typeof( string ).GetMethod( "ToUpper", new Type[] { } );
Func<string, string> toUpper
    = (Func<string, string>)Delegate.CreateDelegate(
          typeof( Func<string, string> ), toUpperMethod );
string upper = toUpper( "test" ); // Will result in "TEST".

Since - just like you - I found these overloads to be unclear, I created two helper functions to clearly separate creating a 'normal' delegate or an open instance delegate. This code, along with a more thorough discussion can be found in my blog post.

Steven Jeuris
  • 18,274
  • 9
  • 70
  • 161
0

If the method is not static then you need to pass in a reference to an instance of the class who's method you are going to be invoking using the delegate.

If you don't know which instance you will be using at the time when you are attempting to create the delegate you will need to store the type and method information for later and then create the Delegate after you have the instance of the class.

EDIT

To answer your comment, the object that you need to pass is an object of the type that contains the method your are trying to bind your delegate to. So based on your code sample it's not the Command object but an object of the class from the DLL.

So, let's say that you have this .NET assembly DLL: myassembly.dll. The assembly contains the following class:

namespace MyNamespace
{
    public class SomeClass
    {
         public SomeClass()
         {
         } 

         public void Method1(object Command, object ExposedVariables)
         {
         }

         public void Method2(object Command, object ExposedVariables)
         {
         }
} 

You would need to create an instance of the class SomeClass before you could create delegates bound to Method1 or Method2 of that class. So, the code which creates the delegate should look like this:

// assuming that method info is a MethodInfo contains information about the method
// that you want to create the delegate for, create an instance of the class which
// contains the method..
object classInstance = Activator.CreateInstance(methodInfo.DeclaringType);
// and then create the delegate passing in the class instance
Delegate.CreateDelegate(typeof(Command.delCmdMethod), classInstance, methodInfo);
Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
  • I have read this but not sure exactly which object I need to use here. Is it Command since that is where the delegate is or the object where the method is? – Jeff Mar 21 '11 at 20:27
  • First off - thank for the help so far... I did as you stated, - saved off the assembly and methodinfo and then tried to Create the delegate using the exact code above and I get the same error. – Jeff Mar 21 '11 at 21:02
  • Have you tried with a different assembly? I would create a new project, and create a simple assembly, set to build as a library, with only one class such as the one I had in my example with two simple methods that don't do anything special and try your code against that. If it still doesn't work try to post more of the source code and we'll try to figure it out.. – Mike Dinescu Mar 22 '11 at 15:32