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

本文关键字:表达式 对象 单个 另一个 | 更新日期: 2023-09-27 18:14:29

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

我最近一直在将一些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。因此,我不能将表达式CompileFunc,因为我可以使用链接到对象。

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

您可以使用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();

您可以:

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方法