给定属性名称,如何创建委托以获取其值

Arg*_*gos 5 c# reflection delegates

我们有一些代码,给定属性名称使用反射来实现Comparer.

我希望存储一个委托/ Func来获取值,而不是每次我们需要获取值时支付反映价格.

鉴于这样的类:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我试着写一个能为我创建委托的函数

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());
}
Run Code Online (Sandbox Code Playgroud)

以下代码适用于获取名称

var person = new Person { Name = "Dave", Age = 42 };

var funcitonToGetName = CreateGetFuncFor<Person>("Name");
Console.WriteLine(funcitonToGetName(person));

var functionToGetAge = CreateGetFuncFor<Person>("Age");
Run Code Online (Sandbox Code Playgroud)

但对于Age proerty,它会抛出一个带有"绑定到目标方法的错误"消息的ArgumentException

我错过了什么?还有另一种方法吗?

Luk*_*keH 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();
}
Run Code Online (Sandbox Code Playgroud)