在LINQ中附加到Func

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在LINQ中附加到Func相关的知识,希望对你有一定的参考价值。

我有一个投影方法

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)

答案

使用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);
}

以上是关于在LINQ中附加到Func的主要内容,如果未能解决你的问题,请参考以下文章

片段未附加到上下文 - 延迟的 UI 更改

循环 LINQ 查询并将结果附加到 DataTable

将 Func 传递给 Linq 到实体 Sum(..)

java 简单的代码片段,展示如何将javaagent附加到运行JVM进程

Android在活动视图中附加片段获取片段已添加错误

片段未附加到上下文