Linq 将表达式应用于表达式中的对象属性

Linq 将表达式应用于表达式中的对象属性,linq,expression,Linq,Expression,我有一个类,它的属性是另一个类。我还有一个从其他类映射的表达式。如何在不编译第二个表达式的情况下将这两个表达式组合成一个表达式 public class ClassA { public int SomeProperty { get; set; } } public class MappedClassA { public int MappedProperty { get; set; } } public class ClassB { public ClassA Clas

我有一个类,它的属性是另一个类。我还有一个从其他类映射的表达式。如何在不编译第二个表达式的情况下将这两个表达式组合成一个表达式

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
        }
    };
}
公共类ClassA
{
公共int SomeProperty{get;set;}
}
公共类MappedClassA
{
公共int-MappedProperty{get;set;}
}
公共B类
{
公共ClassA ClassA属性{get;set;}
//剪断。。。
}
公共类MappedClassB
{
公共MappedClassA MappedClassA属性{get;set;}
}
公共表达式MapAExpression()
{
返回a=>newmappedclassa()
{
MappedProperty=a.SomeProperty
};
}
公共表达式MapBExpression()
{
返回b=>newmappedClassb()
{
//这应该用上面的表达式来完成
MappedClassA属性=新的MappedClassA()
{
MappedProperty=b.ClassAProperty.SomeProperty
}
};
}

这在不编译表达式的情况下是可能的,但遗憾的是,不能使用简单的lambda语法来构造表达式

您必须“手动”使用like和创建表达式树

这会很快变得不可读

我试着从下面的记忆中组合出这样的表达,但我缺乏实践;这是未经测试的,可能还有一些错误

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
        // }
    // };

}
public Expression MapBExpression()
{
//生成ClassB类型的参数。
//这是我们最终的lambda表达式将接受的参数“b”。
var classBparam=Expression.Parameter(typeof(ClassB));
//访问b.ClassA属性;这是属性
//我们要传递给MapAExpression()返回的表达式的
var memberAccess=Expression.MakeMemberAccess(
ClassB参数,
typeof(ClassB).GetProperty(“classapProperty”);
//调用MapAExpression()返回的lambda
//使用参数b.ClassA属性
var invocation=Expression.Invoke(MapAExpression(),memberAccess);
//创建一个新的MappedClassB(),这是将返回的对象
//通过我们当前创建的表达式
var-ctor=Expression.New(typeof(MappedClassB));
//我们想为MappedClassB.MappedClassA属性分配一些内容
var MappedClassA属性=
typeof(MappedClassB).GetProperty(“MappedClassAProperty”);
//具体地说,我们要分配MapAExpression()的结果,
//当使用参数b.ClassAProperty调用时
var MappedClassaaSignment=
Bind(mappedClassAProperty,调用);
//这里我们初始化MappedClassA属性,
//创建新MappedClassB后。
//我们用刚刚创建的赋值来初始化它
var memberInit=Expression.memberInit(ctor,MappedClassaaSignment);
//最后,我们构造了lambda
//给定一个ClassB类型的参数,就可以完成上述所有操作
返回表达式.Lambda(memberInit,classBparam);
//此表达式现在应等效于:
//返回b=>newmappedClassb()
// {
//MappedClassA属性=新的MappedClassA()
// {
//MappedProperty=b.ClassAProperty.SomeProperty
// }
// };
}

我很害怕这个。幸运的是,我找到了一种通过重新设计来实现我想要的东西的方法。