在LINQ中附加到Func

问题描述 投票:0回答:1

我有一个投影方法

public IQueryable<EmpDTO> GetEmployee(Func<Employee, EmpDTO> projection = null)
{
    if(projection == null)
        projection = emp => new EmpDTO {
                                  Id = emp.Id,
                                  Name = emp.Name,
                                  Salary = emp.Salary,    
                                };
    return entities.Employees.Where(e => e.Salary > 10000).Select(projection);
}

它可以扩展如下:

query = classInstance.GetEmployee(emp => new EmpDTO {
                                          Id = emp.Id,
                                          Name = emp.Name,
                                          Salary = emp.Salary,    
                                          Address = emp.Address
                                      });

如何在不重写整个字段的情况下仅将“地址”字段附加到Func(重复字段Id,Name,Salary)

linq lambda entity-framework-core func
1个回答
1
投票

使用Expression,您可以构建一个新的lambda来初始化字段:

public IQueryable<EmpDTO> GetEmployee(Expression<Func<Employee, EmpDTO>> addProj = null) {
    Expression<Func<Employee, EmpDTO>> projection = emp => new EmpDTO {
        Id = emp.Id,
        Name = emp.Name,
        Salary = emp.Salary,
    };

    if (addProj != null) {
        var pBody = ((MemberInitExpression)projection.Body);
        var newBindings = new ReadOnlyCollection<MemberBinding>(pBody.Bindings.Concat(((MemberInitExpression)addProj.Body).Bindings).ToList());
        var newBody = Expression.MemberInit(pBody.NewExpression, newBindings);
        projection = (Expression<Func<Employee, EmpDTO>>) Expression.Lambda(newBody, projection.Parameters);
    }

    return entities.Employees.Where(e => e.Salary > 10000).Select(projection);
}

你也可以从头开始构建整个lambda,但这对我来说似乎更有用。另外,您可以将combine init逻辑封装到扩展方法中:

public static Expression<Func<TIn, TOut>> Add<TIn, TOut>(this Expression<Func<TIn, TOut>> proj, Expression<Func<TIn, TOut>> addProj = null) {
    if (addProj != null) {
        var pBody = ((MemberInitExpression)proj.Body);
        var newBindings = new ReadOnlyCollection<MemberBinding>(pBody.Bindings.Concat(((MemberInitExpression)addProj.Body).Bindings).ToList());
        var newBody = Expression.MemberInit(pBody.NewExpression, newBindings);
        proj = (Expression<Func<TIn, TOut>>)Expression.Lambda(newBody, proj.Parameters);
    }

    return proj;
}

这将GetEmployee身体减少到:

public IQueryable<EmpDTO> GetEmployee(Expression<Func<Employee, EmpDTO>> addProj = null) {
    Expression<Func<Employee, EmpDTO>> projection = emp => new EmpDTO {
        Id = emp.Id,
        Name = emp.Name,
        Salary = emp.Salary,
    };

    if (addProj != null)
        projection = projection.Add(addProj);

    return entities.Employees.Where(e => e.Salary > 10000).Select(projection);
}
© www.soinside.com 2019 - 2024. All rights reserved.