c# - CreateDelegate() System.ArgumentException 方法签名不匹配

标签 c# .net reflection delegates

我一直在尝试使用反射来比较在编译时类型未知的对象,而不是每次尝试使用 CreateDelegate() 时都调用 Invoke()。到目前为止,我已经在基本类型等的通用类型类中使用它,但我遇到了类型为 KeyValuePair 的对象的砖墙。它抛出

System.ArgumentException: 'Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.'

当 CreateDelegate() 被调用时,即使方法签名与提供给 Invoke() 和从 Invoke() 返回的类型相匹配,我也不知道我做错了什么。重现异常的最少代码如下:

static void Main(string[] args)
{
    var kvp = new KeyValuePair<string, string>("test key", "test value");

    var getKeyMethod = typeof(KeyValuePair<string, string>).GetProperty("Key").GetGetMethod();
    Console.WriteLine(getKeyMethod.Invoke(kvp, null));  //works fine

    var getKey = (Func<KeyValuePair<string, string>, string>) getKeyMethod.CreateDelegate(typeof(Func<KeyValuePair<string, string>, string>));  //exception thrown here
    Console.WriteLine(getKey(kvp));  //never gets here
}

我意识到使用表达式树也可以做同样的事情,并且我已经使用完全相同的方法签名实现了这一点,如下所示:

    ParameterExpression targetExp = Expression.Parameter(typeof(KeyValuePair<string, string>), "target");
    MemberExpression propertyExp = Expression.Property(targetExp, typeof(KeyValuePair<string, string>).GetProperty("Key"));
    var getKeyMethod = Expression.Lambda<Func<KeyValuePair<string, string>, string>>(propertyExp, targetExp).Compile();

尽管如此,我想了解这里出了什么问题(表达式树也有点慢,但我主要只是因为无法正常工作而感到恼火)。

最佳答案

KeyValuePair<,>是一个结构。结构和委托(delegate)有特殊规则。要访问实例方法,您本质上需要一个带有 ref 的委托(delegate)范围。例如,以下按预期工作:

// define delegate
delegate string RefDel(ref KeyValuePair<string, string> kvp);

// in method 
var kvp = new KeyValuePair<string, string>("test key", "test value");

var getKeyMethod = typeof(KeyValuePair<string, string>).GetProperty("Key").GetGetMethod();
var getKey = (RefDel)getKeyMethod.CreateDelegate(typeof(RefDel));

Console.WriteLine(getKey(ref kvp));  // "test key"

See here一个活生生的例子。

关于c# - CreateDelegate() System.ArgumentException 方法签名不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66635753/

相关文章:

c# - 如何将表格添加到托盘

c# - IIS后台进程

c# - 在静态类上调用重载的泛型方法

java - BeanUtils.copyProperties 将 Integer null 转换为 0

c# - 如何停止动画WPF?

c# - Xamarin.mac 资源本地化不会因当前文化而改变

c# - 如何检查 RavenDB 中是否存在表(实体)

c# - .NET 应用程序中不稳定的无效 View 状态问题

.net - System.Net.Http.HttpClient 是否受到 HttpWebRequest.AllowWriteStreamBuffering 的影响?

c# - 生成基于填充对象的代码