尝试创建动态委托

发布于 2024-10-24 19:51:30 字数 838 浏览 1 评论 0原文

我正在使用 loadfrom 加载 dll,并迭代这些方法以查找与签名匹配的 dll。当我找到它时,我想将其分配为委托,以便稍后调用它。这就是我正在做的...

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

问题是 - 委托分配不起作用。我收到绑定到目标方法的错误。

我在网上读到,如果方法不是静态的,第二个参数可能是问题。我的方法不是静态的。

有什么想法吗?

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?

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

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

发布评论

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

评论(2

千里故人稀 2024-10-31 19:51:30

尽管 Miky Dinescu 的回答可能会有所帮助,但它只是部分正确。 Delegate.CreateDelegate 这很可能会对您有所帮助。

首先,Miky 是对的,您必须将实例作为第二个参数传递,但只有当您想创建所谓的封闭委托时才会出现这种情况。这意味着实例与方法一起绑定到委托。实际上,这意味着在调用委托时,它将始终在同一个实例上操作。

从你的问题来看,这似乎不是你想要实现的目标。如果您希望在调用委托时能够传递实例,则必须使用 CreateDelegate( Type type, MethodInfo method ) 重载。这允许您创建所谓的开放实例委托

由于调用方法时必须传递实例,这意味着委托类型中需要一个额外的参数。委托类型的第一个参数需要与包含该方法的类的类型相对应。

示例:

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".

因为 - 就像您一样 - 我发现这些重载不清楚,因此我创建了两个辅助函数来明确区分创建“正常”委托或开放实例委托。此代码以及更彻底的讨论 可以在我的博客文章中找到

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.

冰之心 2024-10-31 19:51:30

如果该方法不是静态的,那么您需要传入对类实例的引用,您将使用委托调用该类的方法。

如果您在尝试创建委托时不知道将使用哪个实例,则需要存储类型和方法信息以供稍后使用,然后在拥有该类的实例后创建委托。

编辑

为了回答您的评论,您需要传递的对象是包含您尝试将委托绑定到的方法的类型的对象。因此,根据您的代码示例,它不是 Command 对象,而是 DLL 中的类的对象。

因此,假设您有这个 .NET 程序集 DLL:myassemble.dll。该程序集包含以下类:

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

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

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

您需要先创建类 SomeClass 的实例,然后才能创建绑定到该类的 Method1 或 Method2 的委托。因此,创建委托的代码应如下所示:

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

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