使用表达式树为新 Class 创建 Lambda 表达式选择器
Create Lambda Expression Selector For New Class Using Expression Tree
相关于:
我想使用 Expression Tree
为新 class 创建 Selector
表达式。请考虑此代码:
s => new Allocation
{
Id = s.Id,
UnitName = s.UnitName,
Address = s.NewAddress,
Tel = s.NewTel
}
我有很大的 class (MyClass
),我想 select 它的一些属性。但我想动态创建它。我该怎么做?
谢谢
解决这个问题的方法是编写等效代码,然后反编译它。例如:
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; }
}
现在,如果我编译它并用 "reflector" 反编译它,我得到:
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));
}
注意: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);
相关于:
我想使用 Expression Tree
为新 class 创建 Selector
表达式。请考虑此代码:
s => new Allocation
{
Id = s.Id,
UnitName = s.UnitName,
Address = s.NewAddress,
Tel = s.NewTel
}
我有很大的 class (MyClass
),我想 select 它的一些属性。但我想动态创建它。我该怎么做?
谢谢
解决这个问题的方法是编写等效代码,然后反编译它。例如:
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; }
}
现在,如果我编译它并用 "reflector" 反编译它,我得到:
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));
}
注意: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);