构成表达式树复合DTO(Composing expression trees for composi

2019-10-21 13:08发布

比方说,我有3层以下的DTO

public class Mailing
{
    public long Id { get; set; }
    //...

    public long IdSender  { get; set; }
    public Sender Sender { get; set; }

    public long IdTemplate { get; set; }
    public Template Template { get; set; }
}
public class Sender
{
    public long Id { get; set; }
    public string Email { get; set; }
    //...
}
public class Template
{
    public long Id { get; set; }
    public string Name { get; set; }
    //...
}

我有3个表达式树来管理DAO到DTO的转换:

private static readonly Expression<Func<DaoMailing, Mailing>> ToMailingShort =
        input => new Mailing
                        {
                            Id = input.Id,
                            IdSender = input.IdSender,
                            IdTemplate = input.IdTemplate,
                            // ...
                        };

private static readonly Expression<Func<DaoTemplate, Template>> ToTemplate =
        input => new Template
                        {
                            Id = input.Id,
                            Name = input.Name,
                            // ...
                        };


private static readonly Expression<Func<DaoSender, Sender>> ToSender =
        input => new Sender
                        {
                            Id = input.Id,
                            Email = input.Email,
                            // ...
                        };

如何建立从上述3给定的表达?

private static readonly Expression<Func<DaoMailing, DaoTemplate, DaoSender, MailingFull>> ToMailingFull =
        (input, template, sender) => new Mailing
                        {
                            Id = input.Id,
                            IdSender = input.IdSender,
                            IdTemplate = input.IdTemplate,
                            // ...
                            Template = new Template
                            {
                                Id = template.Id,
                                Name = template.Name,
                                // ...
                            },
                            new Sender
                            {
                                Id = sender.Id,
                                Email = sender.Emai;,
                                // ...
                            }
                        };

其目标是,obviousely,以避免在复合材料一个重写每个单独的转换

Answer 1:

简短的回答是使用AutoMapper ,或编译的表达式转化功能。 这是很容易在C#撰写功能,更难组成表达式。

较长的答案是,这是可能的,但并不容易。 您的代码使用“友好”表达式的语法,但要真正混搭的表情,你就需要使用不友好的版本,这更恶心和难以维持:

    private static readonly Expression<Func<DaoMailing, DaoTemplate, DaoSender, Mailing>> ToMailingFull =
        (Expression<Func<DaoMailing, DaoTemplate, DaoSender, Mailing>>)Expression.Lambda(
            Expression.MemberInit(
                Expression.New(typeof(Mailing).GetConstructor(Type.EmptyTypes)),
                (ToMailingShort.Body as MemberInitExpression).Bindings
                    .Concat(new List<MemberBinding>{
                        Expression.MemberBind(typeof(Mailing).GetProperty("Sender"), (ToSender.Body as MemberInitExpression).Bindings),
                        Expression.MemberBind(typeof(Mailing).GetProperty("Template"), (ToTemplate.Body as MemberInitExpression).Bindings)
                    })
            ),
            ToMailingShort.Parameters[0],
            ToTemplate.Parameters[0],
            ToSender.Parameters[0]
        );


文章来源: Composing expression trees for composite DTO