如何在另一个表达式中的单个对象上重用一个表达式

How do I reuse an Expression on a single object in another Expression

我觉得我遗漏了一些简单的东西,但我还没有找到能回答我问题的文档。

我最近一直在将一些 linq 投影分解为可重用的表达式。它在对集合进行操作时效果很好,但我似乎无法弄清楚如何将表达式应用于另一个表达式中的单个对象。以下是我要完成的示例:

public class Person
{
    public string ID { get; set; }
    public string Name { get; set; }
}

public class PersonDto
{
    public string ID { get; set; }
    public string Name { get; set; }
}

public class Department
{
    Person Manager { get; set; }
    List<Person> Employees { get; set; }
}

public class DepartmentDto
{
    PersonDto Manager { get; set; }
    List<PersonDto> Employees { get; set; }
}

public Expression<Func<Person, PersonDto>> CreatePersonDto = p => new PersonDto
{
    ID = p.ID,
    Name = p.Name
};

public Expression<Func<Department, DepartmentDto>> CreateDepartmentDto = d => new DepartmentDto
{
    Manager = d.Manager // How do I transform this `Person` using `CreatePersonDto`
    Employees = d.Employees.Select(CreatePersonDto) //Does not work either
};

编辑:明确地说,我正在使用需要使用此表达式生成 SQL 语句的 Linq-to-Entities。结果,我无法 Compile 表达式 Func 因为我可以使用 Linq-to-Objects。

您可以:

public static Expression<Func<Department, DepartmentDto>> CreateDepartmentDto = d =>
     new DepartmentDto
        {
            Manager = CreatePersonDto.Compile()(d.Manager),
            Employees = d.Employees.Select(CreatePersonDto.Compile()).ToList() // Or declare Employees as IEnumerable and avoid ToList conversion
        };

显然,您可以存储编译后的 Func

而不是调用两次 Compile 方法

您可以使用 LINQKit 来扩展您在其他表达式中的表达式:

private static Expression<Func<Department, DepartmentDto>> CreateDepartmentDtoUnexpanded = d => new DepartmentDto
{
    Manager = CreatePersonDto.Invoke(d.Manager),
    Employees = d.Employees.Select(employee => CreatePersonDto.Invoke(employee))
        .ToList(),
};
public static Expression<Func<Department, DepartmentDto>> CreateDepartmentDto = CreateDepartmentDtoUnexpanded.Expand();