我有一个属性为另一个类的类。我还有一个表达式,可以映射其他类。如何在不编译第二个表达式的情况下将这两个表达式组合成一个表达式?
public class ClassA
{
public int SomeProperty { get; set; }
}
public class MappedClassA
{
public int MappedProperty { get; set; }
}
public class ClassB
{
public ClassA ClassAProperty { get; set; }
//snip...
}
public class MappedClassB
{
public MappedClassA MappedClassAProperty {get; set; }
}
public Expression<Func<ClassA, MappedClassA>> MapAExpression()
{
return a => new MappedClassA()
{
MappedProperty = a.SomeProperty
};
}
public Expression<Func<ClassB, MappedClassB>> MapBExpression()
{
return b => new MappedClassB()
{
//this should be done with the above expression
MappedClassAProperty = new MappedClassA()
{
MappedProperty = b.ClassAProperty.SomeProperty
}
};
}
答案 0 :(得分:2)
这可以不编译表达式,但遗憾的是不能使用简单的lambda语法来构造表达式。
您必须使用expression methods和Expression.New()等Expression.Lambda()手动创建表达式树#34;
这很快就会变得难以理解。
我尝试从下面的记忆中组装这样的表达,但我缺乏练习;这是未经测试的,可能还有一些漏洞。
public Expression<Func<ClassB, MappedClassB>> MapBExpression()
{
// generate a parameter of type ClassB.
// This is the parameter "b" our final lambda expression will accept.
var classBparam = Expression.Parameter(typeof(ClassB));
// access b.ClassAProperty; this is the property
// that we want to pass to the expression returned by MapAExpression()
var memberAccess = Expression.MakeMemberAccess(
classBparam,
typeof(ClassB).GetProperty("ClassAProperty"));
// invoke the lambda returned by MapAExpression()
//with the parameter b.ClassAProperty
var invocation = Expression.Invoke( MapAExpression(), memberAccess );
// create a new MappedClassB(), this is the object that will be returned
// by the expression we are currently creating
var ctor = Expression.New(typeof(MappedClassB));
// We want to assign something to the MappedClassB.MappedClassAProperty
var mappedClassAProperty =
typeof(MappedClassB).GetProperty("MappedClassAProperty");
// specifically, we want to assign the result of our MapAExpression(),
// when invoked with the parameter b.ClassAProperty
var mappedClassAAssignment =
Expression.Bind(mappedClassAProperty, invocation);
// Here we initialize the MappedClassAProperty,
// after creating the new MappedClassB.
// We initialize it with the assignment we just created
var memberInit = Expression.MemberInit(ctor, mappedClassAAssignment);
// finally, we construct the lambda
//that does all of the above, given a parameter of type ClassB
return Expression.Lambda<Func<ClassB, MappedClassB>>(memberInit, classBparam);
// this expression should now be equivalent to:
// return b => new MappedClassB()
// {
// MappedClassAProperty = new MappedClassA()
// {
// MappedProperty = b.ClassAProperty.SomeProperty
// }
// };
}