我们有一些代码,给定属性名称使用反射来实现Comparer。
我希望存储一个委托/ Func来获取值,而不是每次我们需要获取值时支付反映价格。
鉴于这样的课程:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
我尝试编写一个可以为我创建委托的函数
Func<T, object> CreateGetFuncFor<T>(string propertyName)
{
PropertyInfo prop = typeof(T).GetProperty(propertyName);
return (Func<T, object>)Delegate.CreateDelegate(typeof(Func<T, object>),
null,
prop.GetGetMethod());
}
以下代码适用于获取名称
var person = new Person { Name = "Dave", Age = 42 };
var funcitonToGetName = CreateGetFuncFor<Person>("Name");
Console.WriteLine(funcitonToGetName(person));
var functionToGetAge = CreateGetFuncFor<Person>("Age");
但是对于Age proerty,它会抛出一个带有“绑定到目标方法的错误”消息的ArgumentException
我错过了什么?还有其他办法吗?
答案 0 :(得分:8)
您在编译时知道声明类型但不知道属性类型似乎很奇怪。总之...
您需要额外的步骤将属性值转换为object
,以便它与Func<T,object>
委托的返回类型匹配。 (对于引用类型的属性,额外的步骤不是严格必要的,但不会造成任何伤害。)
Func<T, object> CreateGetFuncFor<T>(string propertyName)
{
var parameter = Expression.Parameter(typeof(T), "obj");
var property = Expression.Property(parameter, propertyName);
var convert = Expression.Convert(property, typeof(object));
var lambda = Expression.Lambda(typeof(Func<T, object>), convert, parameter);
return (Func<T, object>)lambda.Compile();
}
答案 1 :(得分:1)
可能是因为Age基本上被定义为:
public int Age {get; private set;}
并且返回int
的方法无法隐式转换为返回object
的方法,而String
则为。
尝试:
Func<T, R> CreateGetFuncFor<T, R>(string propertyName)
{
PropertyInfo prop = typeof(T).GetProperty(propertyName);
return (Func<T, R>)Delegate.CreateDelegate(typeof(Func<T, R>),
null,
prop.GetGetMethod());
}
然后
var functionToGetAge = CreateGetFuncFor<Person, int>("Age");