djdd87
djdd87

Reputation: 68476

How can I create an Expression within another Expression?

Forgive me if this has been asked already. I've only just started using LINQ. I have the following Expression:

public static Expression<Func<TblCustomer, CustomerSummary>> SelectToSummary()
{
    return m => (new CustomerSummary()
    {
        ID = m.ID,
        CustomerName = m.CustomerName,
        LastSalesContact = // This is a Person entity, no idea how to create it
    });
}

I want to be able to populate LastSalesContact, which is a Person entity.

The details that I wish to populate come from m.LatestPerson, so how can I map over the fields from m.LatestPerson to LastSalesContact. I want the mapping to be re-useable, i.e. I do not want to do this:

LastSalesContact = new Person()
{
   // Etc
}

Can I use a static Expression, such as this:

public static Expression<Func<TblUser, User>> SelectToUser()
{
    return x => (new User()
    {
        // Populate
    });
 }

UPDATE:

This is what I need to do:

return m => (new CustomerSummary()
{
    ID = m.ID,
    CustomerName = m.CustomerName,
    LastSalesContact = new Person()
    {
       PersonId = m.LatestPerson.PersonId,
       PersonName = m.LatestPerson.PersonName,
       Company = new Company()
       {
           CompanyId = m.LatestPerson.Company.CompanyId,
           etc
       }
    }
});

But I will be re-using the Person() creation in about 10-15 different classes, so I don't want exactly the same code duplicated X amount of times. I'd probably also want to do the same for Company.

Upvotes: 4

Views: 213

Answers (3)

Necros
Necros

Reputation: 3034

Can't you just use automapper for that?

public static Expression<Func<TblCustomer, CustomerSummary>> SelectToSummary()
{
    return m => Mapper.Map<TblCustomer, CustommerSummary>(m);
}

You'd have to do some bootstrapping, but then it's very reusable.

UPDATE:

I may not be getting something, but what it the purpose of this function? If you just want to map one or collection of Tbl object to other objects, why have the expression?

You could just have something like this:

var customers = _customerRepository.GetAll(); // returns IEnumerable<TblCustomer>
var summaries = Mapper.Map<IEnumerable<TblCustomer>, IEnumerable<CustomerSummary>>(customers);

Or is there something I missed?

Upvotes: 1

ChaosPandion
ChaosPandion

Reputation: 78272

How about this:

public static Person CreatePerson(TblPerson data)
{
    // ...
}

public static Expression<Func<TblPerson, Person>>  CreatePersonExpression()
{
    return d => CreatePerson(d);
}


return m => (new CustomerSummary()
{
    ID = m.ID,
    CustomerName = m.CustomerName,
    LastSalesContact = CreatePerson(m.LatestPerson)
});

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500675

I don't think you'll be able to use a lambda expression to do this... you'll need to build up the expression tree by hand using the factory methods in Expression. It's unlikely to be pleasant, to be honest.

My generally preferred way of working out how to build up expression trees is to start with a simple example of what you want to do written as a lambda expression, and then decompile it. That should show you how the expression tree is built - although the C# compiler gets to use the metadata associated with properties more easily than we can (we have to use Type.GetProperty).

This is always assuming I've understood you correctly... it's quite possible that I haven't.

Upvotes: 0

Related Questions