C# 创建函数以检索通过反射检索的属性值
我正在编写代码,将我的ORM实体的数据传输到数据集中。因为我不想为每种类型编写特殊的代码来定义需要写哪些属性,所以我目前正在使用反射(对实体的类型调用GetProperties,为该类型建立一个DataTable,然后对每个实体的每个Propertyinfo调用GetValue)。现状:它起作用,但速度很慢 现在我试图建立一个方法,返回一个函数来快速检索某些属性的值,但我在这里遇到了一个困难。到目前为止,我得到的是:C# 创建函数以检索通过反射检索的属性值,c#,reflection,C#,Reflection,我正在编写代码,将我的ORM实体的数据传输到数据集中。因为我不想为每种类型编写特殊的代码来定义需要写哪些属性,所以我目前正在使用反射(对实体的类型调用GetProperties,为该类型建立一个DataTable,然后对每个实体的每个Propertyinfo调用GetValue)。现状:它起作用,但速度很慢 现在我试图建立一个方法,返回一个函数来快速检索某些属性的值,但我在这里遇到了一个困难。到目前为止,我得到的是: /// <summary> /// creates a f
/// <summary>
/// creates a func that will return the value of the given property
/// </summary>
/// <typeparam name="T">type of the entity</typeparam>
/// <param name="propertyInfo">the property to get the value from</param>
/// <returns>a function accepting an instance of T and returning the value of the property</returns>
private Func<T, object> CreateGetPropertyFunc<T>(PropertyInfo propertyInfo)
{
MethodInfo getMethod = propertyInfo.GetGetMethod();
return (Func<T, object>)Delegate.CreateDelegate(typeof(Func<T, object>), getMethod);
}
//
///创建将返回给定属性值的func
///
///实体的类型
///要从中获取值的属性
///接受T实例并返回属性值的函数
私有函数CreateGetPropertyFunc(PropertyInfo PropertyInfo)
{
MethodInfo getMethod=propertyInfo.getMethod();
return(Func)Delegate.CreateDelegate(typeof(Func),getMethod);
}
以下是我的单元测试:
[TestMethod]
public void TestGenerateDelegate()
{
var employee = new Employee
{
Id = 1,
Name = "TestEmployee",
};
Func<Employee, object> getIdValueFunc = CreateGetPropertyFunc<Employee>(typeof(Employee).GetProperty("Id"));
Assert.AreEqual(1, getIdValueFunc(employee));
}
[TestMethod]
public void TestGenerateDelegateName()
{
var employee = new Employee
{
Name = "Test"
};
Func<Employee, object> getNameValueFunc = CreateGetPropertyFunc<Employee>(typeof(Employee).GetProperty("Name"));
Assert.AreEqual("Test", getNameValueFunc(employee));
}
[TestMethod]
public void TestGenerateDelegate()
{
var employee=新员工
{
Id=1,
Name=“TestEmployee”,
};
Func getIdValueFunc=CreateGetPropertyFunc(typeof(Employee).GetProperty(“Id”);
Assert.AreEqual(1,getIdValueFunc(雇员));
}
[测试方法]
public void TestGenerateDelegateName()
{
var employee=新员工
{
Name=“测试”
};
Func getNameValueFunc=CreateGetPropertyFunc(typeof(Employee).GetProperty(“名称”);
AreEqual(“Test”,getNameValueFunc(employee));
}
当我调用第一个方法时,抛出ArgumentException,其中包含消息“绑定到目标方法时异常”(已翻译,可能是不同的文本)。第二次测试反而通过了
我很确定我没有正确处理CreateDelegate方法。谁能给我指一下正确的方向吗
更新:
正如PetSerAI statet所说,这似乎是方差的问题,值原语类型不能通过CreateDelegate作为对象返回…您可以调用
getMethod
:
private Func<T, object> CreateGetPropertyFunc<T>(PropertyInfo propertyInfo)
{
MethodInfo getMethod = propertyInfo.GetGetMethod();
return o => getMethod.Invoke(o, BindingFlags.Default, null, null, CultureInfo.CurrentCulture);
}
private Func CreateGetPropertyFunc(PropertyInfo PropertyInfo)
{
MethodInfo getMethod=propertyInfo.getMethod();
return o=>getMethod.Invoke(o,BindingFlags.Default,null,null,CultureInfo.CurrentCulture);
}
您可以调用您的getMethod
:
private Func<T, object> CreateGetPropertyFunc<T>(PropertyInfo propertyInfo)
{
MethodInfo getMethod = propertyInfo.GetGetMethod();
return o => getMethod.Invoke(o, BindingFlags.Default, null, null, CultureInfo.CurrentCulture);
}
private Func CreateGetPropertyFunc(PropertyInfo PropertyInfo)
{
MethodInfo getMethod=propertyInfo.getMethod();
return o=>getMethod.Invoke(o,BindingFlags.Default,null,null,CultureInfo.CurrentCulture);
}
为什么不一直使用泛型,让编译器为您创建委托
public static class Ext
{
public static Func<T, TProp> CreateGetPropertyFunc<T, TProp>(this T obj, Func<T, TProp> func)
{
return func;
}
}
如果您事先没有
t
的实际实例,或者只是不想使用扩展方法:
public Func<T, object> CreateGetPropertyFunc<T>(Func<T, object> func)
{
return func;
}
public Func CreateGetPropertyFunc(Func Func)
{
返回函数;
}
然后:
var getterForId=CreateGetPropertyFunc(x=>x.Id);
对象结果=getterForId(员工);
//结果必须为“对象”(除非显式强制转换)
(前者在性能方面更好,因为像
int
这样的值类型不会被装箱,类型安全性也会被保留)为什么不一直使用泛型,让编译器为您创建委托
public static class Ext
{
public static Func<T, TProp> CreateGetPropertyFunc<T, TProp>(this T obj, Func<T, TProp> func)
{
return func;
}
}
如果您事先没有
t
的实际实例,或者只是不想使用扩展方法:
public Func<T, object> CreateGetPropertyFunc<T>(Func<T, object> func)
{
return func;
}
public Func CreateGetPropertyFunc(Func Func)
{
返回函数;
}
然后:
var getterForId=CreateGetPropertyFunc(x=>x.Id);
对象结果=getterForId(员工);
//结果必须为“对象”(除非显式强制转换)
(前者在性能方面更好,因为像
int
这样的值类型不会被装箱,并且类型安全性会被保留)CreateDelegate(类型, MethodInfo)
绑定到一个静态方法(您没有静态方法,这就是您得到错误的原因)
您只能将Delegate.CreateDelegate
用于此版本的实例方法:CreateDelegate(Type, 对象 MethodInfo)
创建表示指定类型的指定类型的委托
静态或实例方法,具有指定的第一个参数
根据PetSerAl的评论,您应该传递'null'作为'first argument',以创建一个“open delegate”,将实例传递到其中
// In this case, the delegate has one more
// argument than the instance method; this argument comes
// at the beginning, and represents the hidden instance
// argument of the instance method. Use delegate type D1
// with instance method M1.
//
d1 = (D1) Delegate.CreateDelegate(typeof(D1), null, mi1);
// An instance of C must be passed in each time the
// delegate is invoked.
//
d1(c1, "Hello, World!");
CreateDelegate(类型, MethodInfo)
绑定到一个静态方法(您没有静态方法,这就是您得到错误的原因)
您只能将Delegate.CreateDelegate
用于此版本的实例方法:CreateDelegate(Type, 对象 MethodInfo)
创建表示指定类型的指定类型的委托
静态或实例方法,具有指定的第一个参数
根据PetSerAl的评论,您应该传递'null'作为'first argument',以创建一个“open delegate”,将实例传递到其中
// In this case, the delegate has one more
// argument than the instance method; this argument comes
// at the beginning, and represents the hidden instance
// argument of the instance method. Use delegate type D1
// with instance method M1.
//
d1 = (D1) Delegate.CreateDelegate(typeof(D1), null, mi1);
// An instance of C must be passed in each time the
// delegate is invoked.
//
d1(c1, "Hello, World!");
可以使用表达式树动态创建引用指定属性的委托:
private Func<T, object> CreateGetPropertyFunc<T>(PropertyInfo propertyInfo) {
ParameterExpression p = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, object>>(
Expression.Convert(Expression.Property(p, propertyInfo), typeof(object)),
p
).Compile();
}
private Func CreateGetPropertyFunc(PropertyInfo PropertyInfo){
ParameterExpression p=表达式参数(typeof(T));
返回表达式.Lambda(
Expression.Convert(Expression.Property(p,propertyInfo),typeof(object)),
P
).Compile();
}
您可以使用表达式树动态创建委托,委托引用指定的属性:
private Func<T, object> CreateGetPropertyFunc<T>(PropertyInfo propertyInfo) {
ParameterExpression p = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, object>>(
Expression.Convert(Expression.Property(p, propertyInfo), typeof(object)),
p
).Compile();
}
private Func CreateGetPropertyFunc(PropertyInfo PropertyInfo){
ParameterExpression p=表达式参数(typeof(T));
返回表达式.Lambda(
表达式.Convert(E)