首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CreateDelegate错误: System.ArgumentException无法绑定到目标方法

CreateDelegate错误: System.ArgumentException无法绑定到目标方法
EN

Stack Overflow用户
提问于 2021-02-11 15:14:53
回答 1查看 663关注 0票数 0

我有一个应用程序,它接受外部应用程序的dll,查找指定的类和方法。然后它从这个外部方法中获取methodinfo,然后尝试通过Delegate.CreateDelegate创建一个委托。

我不断地

代码语言:javascript
复制
System.ArgumentException: 'Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.'

我已经进行了一些提取代码,以使它更容易共享和调试,以及编写一个小的简单的外部应用程序来阅读。见下面的代码:

外部应用程序示例作为库(.Net Framework4.8)

代码语言:javascript
复制
using System;

namespace MethodLib
{
    public class PrintText
    {
        public string Print(string textToPrint, int number)
        {
            return $"{ PrintPrivate(textToPrint) }: {number}";
        }

        public static string PrintStatic(string textToPrint)
        {
            return textToPrint;
        }

        public void PrintVoid(string textToPrint)
        {
            Console.WriteLine(textToPrint);
        }

        private string PrintPrivate(string textToPrint)
        {
            return $"This is { textToPrint }";
        }
    }
}

应用程序到CreateDelegate

MethodInfo创建

代码语言:javascript
复制
using System;
using System.Reflection;

namespace DelegateApp
{
    public class PluginSupport
    {
        public MethodInfo GetMethodInfo(string methodName, string externalLocation)
        {
            var instance = Activator.CreateInstance(Assembly.LoadFrom(externalLocation)
                .GetType("MethodLib.PrintText"));

            var methodInfo = instance.GetType()
                .GetMethod(methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);

            return methodInfo;
        }
    }
}

创建代理部件

代码语言:javascript
复制
namespace DelegateApp
{
    public class MethodGenerator
    {
        private PluginSupport _pluginSupport;

        public MethodGenerator()
        {
            _pluginSupport = new PluginSupport();
        }

        public MethodDetails Create(string methodName, string path)
        {
            var method = _pluginSupport.GetMethodInfo(methodName, path);

            if (Equals(method, null))
            {
                throw new KeyNotFoundException($"Method '{ methodName }' doesn't exist in class");
            }

            return new MethodDetails
            {
                MethodName = method.Name,
                ComponentName = method.DeclaringType.Name,
                FriendlyName = method.DeclaringType.Name,
                Parameters = method.GetParameters(),
                LogicalPath = method.DeclaringType.Assembly.Location,
                Method = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), method)
            };
        }
    }
}

我试过什么

所以读了很多不同的帖子我想我正在用的电话

(Func<string>)Delegate.CreateDelegate(typeof(Func<string>), method)实际上只适用于静态方法,而且由于我对所有公共方法感兴趣,所以我缺少了一个目标/实例。

因此,从其他示例中,您需要创建实例并将其传递到其中,因此我使用了var myInstance = Actovator.CreateInstance,然后也传递了这个变量,结果如下所示

(Func<string>)Delegate.CreateDelegate(typeof(Func<string>), myInstance, method)

我也试过用这个

public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase);

所有这一切都在不断地

代码语言:javascript
复制
System.ArgumentException: 'Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.'

我唯一能让它发挥作用的时候,是我做以下事情的时候:

来自外部应用程序的methodName = PrintStatic

代码语言:javascript
复制
var methodInfo = instance.GetType()
                .GetMethod(methodName, BindingFlags.Public | BindingFlags.Static);

var deleg = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>),null, method)

当然,这不是我想要的,因为这只对我来说是静态的,我也要非静态的。但是即使这样,如果我将BindingFlags.Instance添加到混合中,静态也会抛出相同的错误。

如果我还删除了BindingFlags.InstancemethodName = Print,那么methodInfo是null。

我的问题

关于Delegate.CreateDelegate

  • What代码,我不理解/缺少什么?我错过了,因为我是expecting?

  • Is,有一种不同的方法来做同样的事情吗?在代码的后面创建代表的

  • ,但是如果只在方法信息上使用调用而不是创建一个委托,然后调用它,那么会受到惩罚吗?

  • 为什么如果省略了BindingFlags.Instance,就不给我公开的非静态成员呢?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-11 21:32:55

多亏了@Charlieface,我才意识到我的签名类型与创建委托不相对应。

因此,在这个示例代码中,我最终得到的结果是在MethodGenerator类中执行以下操作

  1. 从method if获取parameters
  2. ,遍历这些参数并将它们添加到类型列表中,并获取每个param
  3. 的类型,在其中我不知道它需要的类型数,并将其替换为来自methodinfo +输出类型

H 112的params数量,检查是否有方法isstatic,并据此将其设置为H 214G 215

代码语言:javascript
复制
methHead = method.IsStatic
                ? Delegate.CreateDelegate(delegateFunc.MakeGenericType(types.ToArray()), null, method)
                : Delegate.CreateDelegate(delegateFunc.MakeGenericType(types.ToArray()), instance, method);  

我猜这是一些复杂的代码,但是它可以工作,并且需要对它进行改进,或者将它放到我们想要使用的实际代码库中。但正如@Charlieface提到的,if you don't know the type, there isn't much point to the delegate.

最后一段代码

代码语言:javascript
复制
 public MethodDetails Create(string methodName, string path)
        {
            var method = _pluginSupport.GetMethodInfo(methodName, path);

            if (Equals(method, null))
            {
                throw new KeyNotFoundException($"Method '{ methodName }' doesn't exist in class");
            }

            var instance = Activator.CreateInstance(method.DeclaringType);

            List<Type> types = new List<Type>();
            var methodPrams = method.GetParameters();
            
            foreach (var item in methodPrams)
            {
                types.Add(Type.GetType(item.ParameterType.UnderlyingSystemType.FullName));
            }

            var funcType = typeof(Func<>);

            var delegateFunc = Type.GetType(funcType.FullName.Replace("1", (methodPrams.Length + 1).ToString()));

            Delegate methHead;

                types.Add(typeof(string));

            methHead = method.IsStatic
                ? Delegate.CreateDelegate(delegateFunc.MakeGenericType(types.ToArray()), null, method)
                : Delegate.CreateDelegate(delegateFunc.MakeGenericType(types.ToArray()), instance, method);          

            return new MethodDetails
            {
                MethodName = method.Name,
                ComponentName = method.DeclaringType.Name,
                FriendlyName = method.DeclaringType.Name,
                Parameters = method.GetParameters(),
                LogicalPath = method.DeclaringType.Assembly.Location,
                Method = methHead
            };
        }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66157420

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档