C# 创建函数以检索通过反射检索的属性值

C# 创建函数以检索通过反射检索的属性值,c#,reflection,C#,Reflection,我正在编写代码,将我的ORM实体的数据传输到数据集中。因为我不想为每种类型编写特殊的代码来定义需要写哪些属性,所以我目前正在使用反射(对实体的类型调用GetProperties,为该类型建立一个DataTable,然后对每个实体的每个Propertyinfo调用GetValue)。现状:它起作用,但速度很慢 现在我试图建立一个方法,返回一个函数来快速检索某些属性的值,但我在这里遇到了一个困难。到目前为止,我得到的是: /// <summary> /// creates a f

我正在编写代码,将我的ORM实体的数据传输到数据集中。因为我不想为每种类型编写特殊的代码来定义需要写哪些属性,所以我目前正在使用反射(对实体的类型调用GetProperties,为该类型建立一个DataTable,然后对每个实体的每个Propertyinfo调用GetValue)。现状:它起作用,但速度很慢

现在我试图建立一个方法,返回一个函数来快速检索某些属性的值,但我在这里遇到了一个困难。到目前为止,我得到的是:

  /// <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)