C# 给定属性名称,如何创建委托以获取其值
我们有一些给定属性名的代码使用反射实现比较器 我希望存储一个委托/Func来获取值,而不是每次需要获取值时都要支付反射代价 对于这样一个类:C# 给定属性名称,如何创建委托以获取其值,c#,reflection,delegates,C#,Reflection,Delegates,我们有一些给定属性名的代码使用反射实现比较器 我希望存储一个委托/Func来获取值,而不是每次需要获取值时都要支付反射代价 对于这样一个类: public class Person { public string Name { get; set; } public int Age { get; set; } } 我试图编写一个函数来为我创建一个委托 Func<T, object> CreateGetFuncFor<T>(string propertyNa
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());
}
Func createGetFunfor(字符串属性名称)
{
PropertyInfo prop=typeof(T).GetProperty(propertyName);
return(Func)Delegate.CreateDelegate(typeof(Func),
无效的
prop.getMethod());
}
下面的代码可以很好地用于获取名称
var person = new Person { Name = "Dave", Age = 42 };
var funcitonToGetName = CreateGetFuncFor<Person>("Name");
Console.WriteLine(funcitonToGetName(person));
var functionToGetAge = CreateGetFuncFor<Person>("Age");
var person=newperson{Name=“Dave”,年龄=42};
var funcitonToGetName=CreateGetFuncFor(“名称”);
Console.WriteLine(functionToGetName(person));
var functionToGetAge=CreateGetFuncFor(“年龄”);
但是对于Age proerty,它抛出一个ArgumentException,并显示消息“Error binding to target method”
我错过了什么?还有其他方法吗?这可能是因为年龄基本上被定义为:
public int Age {get; private set;}
返回int
的方法不能隐式转换为返回对象的方法,而字符串
是
尝试:
Func createGetFunfor(字符串属性名称)
{
PropertyInfo prop=typeof(T).GetProperty(propertyName);
return(Func)Delegate.CreateDelegate(typeof(Func),
无效的
prop.getMethod());
}
然后
var functionToGetAge = CreateGetFuncFor<Person, int>("Age");
var functionToGetAge=CreateGetFuncFor(“年龄”);
奇怪的是,您在编译时知道声明类型,但不知道属性类型。无论如何
您需要额外的步骤将属性值转换为对象
,以便它与Func
委托的返回类型匹配。(对于引用类型的属性来说,额外的步骤不是绝对必要的,但不会造成任何伤害。)
Func createGetFunfor(字符串属性名称)
{
var参数=表达式参数(类型(T),“obj”);
var property=Expression.property(参数,propertyName);
var convert=Expression.convert(属性,typeof(对象));
var lambda=Expression.lambda(typeof(Func),convert,parameter);
返回(Func)lambda.Compile();
}
不幸的是,在我想使用此属性的代码中,我不知道该属性的类型。如果不知道类型,您将如何处理年龄?您能稍微扩展一下您的用例吗?最终,这些值会在调用System.Collections.Comparer.Default.CompareOh时使用。我同意,但我目前无法更改代码的这些部分。
var functionToGetAge = CreateGetFuncFor<Person, int>("Age");
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();
}