使用表达式树为新类创建Lambda表达式选择器

Ari*_*ian 4 c# linq lambda expression-trees c#-6.0

相关:

为选择器创建表达式树

使用3个条件创建Lambda表达式

转换包含到表达式树

将List.Contains转换为表达式树

我想为新类创建Selector表达式Expression Tree.请考虑以下代码:

s => new Allocation
     {
         Id = s.Id,
         UnitName = s.UnitName,
         Address = s.NewAddress,
         Tel = s.NewTel
      }
Run Code Online (Sandbox Code Playgroud)

我有一个大类(MyClass),我想选择它的一些属性.但我想动态创建它.我怎么能这样做?

谢谢

Mar*_*ell 6

解决这个问题的方法是编写等效代码,然后对其进行反编译.例如:

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        ShowMeTheLambda<Foo, Allocation>(s => new Allocation
        {
            Id = s.Id,
            UnitName = s.UnitName,
            Address = s.NewAddress,
            Tel = s.NewTel
        });
    }
    static void ShowMeTheLambda<TFrom, TTo>(Expression<Func<TFrom, TTo>> lambda)
    { }
}
class Foo
{
    public int Id { get; set; }
    public string UnitName { get; set; }
    public string NewTel { get; set; }
    public string NewAddress { get; set; }
}
class Allocation
{
    public int Id { get; set; }
    public string UnitName { get; set; }
    public string Tel { get; set; }
    public string Address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我编译它并用"反射器"反编译它,我得到:

private static void Main()
{
    ParameterExpression expression;
    MemberBinding[] bindings = new MemberBinding[] { Expression.Bind((MethodInfo) methodof(Allocation.set_Id), Expression.Property(expression = Expression.Parameter(typeof(Foo), "s"), (MethodInfo) methodof(Foo.get_Id))), Expression.Bind((MethodInfo) methodof(Allocation.set_UnitName), Expression.Property(expression, (MethodInfo) methodof(Foo.get_UnitName))), Expression.Bind((MethodInfo) methodof(Allocation.set_Address), Expression.Property(expression, (MethodInfo) methodof(Foo.get_NewAddress))), Expression.Bind((MethodInfo) methodof(Allocation.set_Tel), Expression.Property(expression, (MethodInfo) methodof(Foo.get_NewTel))) };
    ParameterExpression[] parameters = new ParameterExpression[] { expression };
    ShowMeTheLambda<Foo, Allocation>(Expression.Lambda<Func<Foo, Allocation>>(Expression.MemberInit(Expression.New(typeof(Allocation)), bindings), parameters));

}
Run Code Online (Sandbox Code Playgroud)

注意:memberof并且methodof实际上并不存在于C#中 - 您可以通过反射手动获取方法信息,也可以使用Expression.PropertyOrField.因此我们可以将其重写为:

ParameterExpression expression = Expression.Parameter(typeof(Foo), "s");
MemberBinding[] bindings = new MemberBinding[]
{
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.Id)), Expression.PropertyOrField(expression, nameof(Foo.Id))),
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.UnitName)), Expression.PropertyOrField(expression, nameof(Foo.UnitName))),
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.Address)), Expression.PropertyOrField(expression, nameof(Foo.NewAddress))),
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.Tel)), Expression.PropertyOrField(expression, nameof(Foo.NewTel))),
};
ParameterExpression[] parameters = new ParameterExpression[] { expression };
var lambda = Expression.Lambda<Func<Foo, Allocation>>(Expression.MemberInit(Expression.New(typeof(Allocation)), bindings), parameters);
Run Code Online (Sandbox Code Playgroud)