2

Как я могу объединить предложение select в linq с объектами, чтобы проектировать в анонимный тип?
Предположим, что у меня есть эти объекты:Объединить предложения select в linq с объектами с анонимными типами

public class Address 
{ 
    public string City { get; set; } 
    public int ZipCode { get; set; } 
    //other properties 
} 

public class Person 
{ 
    public string Name { get; set; } 
    public Address Address { get; set; } 
    //a LOT of other properties 
} 

//extend person class with employee specific properties 
public class Employee : Person 
{ 
    public double Salary { get; set; } 
    public Person Manager { get; set; } 
} 

Иногда мне только нужно, чтобы запросить несколько свойств моего Person класса:

Context.Persons.Where(...).Select(p => new 
{ 
    p.Name, 
    PersonCity = p.Address.City, 
    //other needed properties 
}); 

И я также необходимо запросить те же свойства мой класс сотрудников плюс особые свойства:

Context.Employees.OfType<Employee>().Where(...).Select(e => new 
{ 
    e.Salary, 
    ManagerName = e.Manager.Name, 
    e.Name, 
    PersonCity = e.City.Name, 
    //other needed properties identical as the previous select with Person entity 
}); 

Возможно ли использовать манипуляции с выражением-деревьями (или другое решение) для объединения двух предложений select, чтобы не дублировать все предложения select из моего объекта Person?

Нечто подобное:

var personSelect = p => new { 
    p.Name, 
    PersonCity = p.Address.City, 
    //other needed properties 
}; 

var employeeSelect = personSelect.Combine(e => new { 
    e.Salary, 
    ManagerName = e.Manager.Name 
}); 

context.Employees.OfType<Employee>().Where(...).Select(employeeSelect).FirstOrDefault(); 
// returns an anonymous object 
// { 
//  Name = "Joachim", 
//  PersonCity = "Lyon", 
//  <other Person properties> 
//  Salary = 65432.10, 
//  ManagerName = "Samuel" 
// } 
+0

Вы в основном хотите реализацию для выражения 'Expression Combine (выражение > e1, выражение ) где TInput2: TInput1'? – Shlomo

+0

Ой, подождите, это не сработает. Я вижу, что говорит свичок. Анонимный тип, созданный в lambda в 'employeeSelect', недостаточно исчерпывающий, и функция не может вернуть новый анонимный тип. – Shlomo

+0

Функция должна иметь подпись 'Expression > Combine (выражение > e1, выражение >), где TInput2: TInput1' и 'TOutput3' не существует во время компиляции. – Shlomo

ответ

2

Нет, нет никакого способа сделать именно то, что вы просите. Проблема в том, что каждый анонимный тип должен быть создан во время компиляции, но деревья выражений работают во время выполнения.

Я вижу два пути, чтобы работать вокруг этого:

  1. Ваш анонимный тип для Employee имели бы свойство что-то вроде PersonData, который будет содержать анонимный тип с информацией из Person.
  2. Вы бы создали обычные типы, такие как PersonData и EmployeeData (который наследуется от PersonData). Каждый тип мог бы дать вам выражение для его создания, и выражение EmployeeData будет вычисляться на основе выражения PersonData.

В обоих случаях вам понадобятся некоторые деревья с деревьями выражений, но это не должно быть трудно сделать.