Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 给定属性名称,如何创建委托以获取其值_C#_Reflection_Delegates - Fatal编程技术网

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

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

我们有一些给定属性名的代码使用反射实现比较器

我希望存储一个委托/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());
}
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();
}