Jonny Piazzi
Jonny Piazzi

Reputation: 3784

Combine two Convert Expressions

Scenario:

Some entity classes:

public class BookEntity
{
    public int IdBook { get; set; }
    public string Title { get; set; }
}

public class StudentEntity
{
    public int IdStudent { get; set; }
    public string Name { get; set; }
}

public class LoanEntity
{
    public int IdLoan { get; set; }
    public StudentEntity Student { get; set; }
    public BookEntity Book { get; set; }
}

And some data transfer object classes:

public class BookDTO
{
    public int IdBook { get; set; }
    public string Title { get; set; }
}

public class StudentDTO
{
    public int IdStudent { get; set; }
    public string Name { get; set; }
}

public class LoanDTO
{
    public int IdLoan { get; set; }
    public StudentDTO Student { get; set; }
    public BookDTO Book { get; set; }
}

And I already have this expressions (that convert entity in dto):

Expression<Func<BookEntity, BookDTO>> pred1 = e => new BookDTO
{
    IdBook = e.IdBook,
    Title = e.Title
};

Expression<Func<StudentEntity, StudentDTO>> pred2 = e => new StudentDTO
{
    IdStudent = e.IdStudent,
    Name = e.Name
};

Goal:
Now I want to create an expression that convert LoanEntity in LoanDTO. Something like:

Expression<Func<LoanEntity, LoanDTO>> pred3 = e => new LoanDTO
{
    IdLoan = e.IdLoan,
    Book = new BookDTO
    {
        IdBook = e.Book.IdBook,
        Title = e.Book.Title
    },
    Student = new StudentDTO
    {
        IdStudent = e.Student.IdStudent,
        Name = e.Student.Name
    }
};

The Problem:

If you notice the pred3 expression is formed by the same code of pred1 and pred2 expression.

So is it possible to create pred3 by using pred1 and pred2 to avoid code duplication?

Upvotes: 2

Views: 84

Answers (2)

Aron
Aron

Reputation: 15772

Have you tried using Install-Package AutoMapper? Its a library that solves your problem completely.

var config = new MapperConfiguration(cfg => 
{
  cfg.CreateMap<LoanEntity, LoanDTO>();
  cfg.CreateMap<BookEntity, BookDTO>();
  cfg.CreateMap<StudentEntity, StudentDTO>();
});
var mapper = new ExpressionBuilder(config);

Expression<Func<LoanEntity, LoanDTO>> mappingExpression = mapper.CreateMapExpression<LoanEntity, LoanDTO>();

Upvotes: 3

Arturo Menchaca
Arturo Menchaca

Reputation: 15982

Is possible but you will have to call Compile() method in expressions pred1 and pred2 to invoke it:

Expression<Func<LoanEntity, LoanDTO>> pred3 = e => new LoanDTO
{
    IdLoan = e.IdLoan,
    Book = pred1.Compile()(e.Book),
    Student = pred2.Compile()(e.Student)
};

But you can only works with Func<,>:

Func<BookEntity, BookDTO> pred1 = e => new BookDTO
{
    IdBook = e.IdBook,
    Title = e.Title
};

Func<StudentEntity, StudentDTO> pred2 = e => new StudentDTO
{
    IdStudent = e.IdStudent,
    Name = e.Name
};

Then, you can use it like this:

Func<LoanEntity, LoanDTO> pred3 = e => new LoanDTO
{
    IdLoan = e.IdLoan,
    Book = pred1(e.Book),
    Student = pred2(e.Student)
};

Upvotes: 1

Related Questions