从给定的类型创建 Expression<Func<T, object>>

thi*_*hat -1 c# reflection lambda expression

我希望通过在代表给定类型的属性成员访问的代码中构建表达式来动态使用 CsvHelper。

我试图将这些表达式传递给的方法具有以下签名:

    public virtual CsvPropertyMap<TClass, TProperty> Map<TProperty>( Expression<Func<TClass, TProperty>> expression )
    {
        //
    }
Run Code Online (Sandbox Code Playgroud)

因此,对于要映射的任何给定类型,您通常会调用它,如下所示(对于具有名为“stringProperty”的属性的类型):

mapper.Map(x => x.StringProperty);
Run Code Online (Sandbox Code Playgroud)

传入一个 lambda 表达式,该 lambda 表达式在内部转换为 Expression<Func<T, object>>

我尝试使用表达式在代码中创建此表达式。在编译时它一切正常(因为它返回一个Expression<Func<TModel, object>>),但在运行时我得到一个异常“不是成员访问”。这是采用表示我要映射的属性的 PropertyInfo 对象的代码:

    private Expression<Func<TModel, object>> CreateGetterExpression( PropertyInfo propertyInfo )
    {
        var getter = propertyInfo.GetGetMethod();

        Expression<Func<TModel, object>> expression = m => getter.Invoke( m, new object[] { } );
        return expression;
    }
Run Code Online (Sandbox Code Playgroud)

基本上,如何在代码中正确构建该表达式?

Geo*_*ria 5

试试看起来像这样的东西:

    public static Expression<Func<T, P>> GetGetter<T, P>(string propName)
    {
        var parameter = Expression.Parameter(typeof(T));
        var property = Expression.Property(parameter, propName);
        return Expression.Lambda<Func<T, P>>(property, parameter);
    }

    public static Expression<Func<T, P>> GetGetter<T, P>(PropertyInfo propInfo)
    {
        var parameter = Expression.Parameter(typeof(T));
        var property = Expression.Property(parameter, propInfo);
        return Expression.Lambda<Func<T, P>>(property, parameter);
    }
Run Code Online (Sandbox Code Playgroud)

这是用法示例:

    private class TestCalss
    {
        public int Id { get; set; }
    }

    private static void Main(string[] args)
    {
        var getter = GetGetter<TestCalss, int>(typeof(TestCalss).GetProperty("Id")).Compile();
        Console.WriteLine(getter(new TestCalss { Id = 16 }));
    }
Run Code Online (Sandbox Code Playgroud)