从MethodInfo创建Func委托遇绑定异常,求问题原因及解决方案
解决委托绑定与反射属性获取的签名不匹配问题
你的异常根源在于委托签名和创建方式不匹配,我来拆解一下问题,再给你两种可行的修正方案:
错误原因分析
你用了Delegate.CreateDelegate的这个重载:
Delegate.CreateDelegate(Type delegateType, object target, MethodInfo method)
这个重载是用来创建绑定到特定实例的委托,此时委托的签名不需要包含实例参数——因为实例已经提前绑定到target参数里了。但你定义的Func<TestClass, string>是需要接收一个TestClass实例作为参数的,这就和方法签名(实例属性的getter是无参数的,因为它依赖调用实例)不兼容,所以抛出了签名不匹配的异常。
方案一:创建绑定到特定实例的无参数委托
如果你只需要获取单个固定实例的属性值,可以把委托类型改成Func<string>,这样就和getter方法的签名匹配了:
TestClass test = new TestClass(){DummyProp= "appo"}; string prop = "DummyProp"; MethodInfo method = typeof(TestClass).GetProperty(prop).GetGetMethod(); // 绑定到test实例,委托不需要再传实例参数 Func<string> getter = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), test, method); Console.WriteLine(getter()); // 直接调用,不用传test
方案二:创建可复用的带实例参数的委托
如果需要用同一个委托获取多个不同TestClass实例的属性值,就要用另一个重载,不传入目标实例,让委托自己接收实例参数:
TestClass test = new TestClass(){DummyProp= "appo"}; TestClass test2 = new TestClass(){DummyProp= "another value"}; string prop = "DummyProp"; MethodInfo method = typeof(TestClass).GetProperty(prop).GetGetMethod(); // 不绑定实例,委托需要接收TestClass实例作为参数 Func<TestClass, string> getter = (Func<TestClass, string>)Delegate.CreateDelegate(typeof(Func<TestClass, string>), method); Console.WriteLine(getter(test)); // 输出appo Console.WriteLine(getter(test2)); // 输出another value
额外优化建议
如果你的属性类型可能不是string,可以用泛型委托来做更通用的实现,比如:
public static Func<T, TProp> CreatePropertyGetter<T, TProp>(string propertyName) { PropertyInfo propInfo = typeof(T).GetProperty(propertyName); MethodInfo getMethod = propInfo.GetGetMethod(); return (Func<T, TProp>)Delegate.CreateDelegate(typeof(Func<T, TProp>), getMethod); }
这样调用的时候就可以直接用:
var getter = CreatePropertyGetter<TestClass, string>("DummyProp"); Console.WriteLine(getter(test));
内容的提问来源于stack exchange,提问作者Daniele Sartori
相关产品推荐
相关产品推荐

