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 dele开发者_开发问答gate 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?
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.
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);
精彩评论