在C#中将Func <t1,bool>转换为Func <t2,bool>

时间:2015-08-29 09:39:06

标签: c# lambda expression

如何将Func<DepartmentViewModel, bool>转换为 Func<Department, bool>

我看过很多关于这个问题的帖子,但没有一个可以帮助我。

我称之为此功能:

public DepartmentViewModel GetSingle(Expression<Func<DepartmentViewModel, bool>> whereCondition)

来自GUI层,如下所示:

_departmentService.GetSingle(de => de.Id ==id));

和位于我的业务层的GetSingle内部函数我必须调用

public IEnumerable<Department> GetAll(Func<Department, bool> predicate = null)

GetAll函数接受Func<Department, bool>类型

这是我的目标:

class Department {
   public string name
}

class DepartmentViewModel{
   public string name
}

方面,我找到了最佳答案:  Func<DepartmentViewModel, bool> some_function = whereCondition.Compile();  Func<Department, bool> converted = d => some_function( new DepartmentViewModel { Id=d.Id, Description=d.Descriptions } );

2 个答案:

答案 0 :(得分:1)

您无法将Func<T1,bool>更改为Func<T2,bool>,但您可以转换相同的表达式。

这需要一些工作,首先你必须传递Expression<Func<T,bool>>,然后你可以轻松转换表达式以匹配传入的参数。

所以你可以改变你的方法,

Expression<Func<DepartmentViewModel,bool>> srcLambda = 
     x => x.DepartmentName.StartsWith("Admin")

Expression<Func<Department,bool>> destLambda = 
     ConvertTo<Department,DepartmentViewModel>( srcLambda);

这假设DepartmentViewModel(DTO)与Department具有相同的字段。否则,您必须稍微更改代码以满足您的需求。

public static Expression<Func<TDest,bool>> 
      ConvertTo<TSrc,TDest>(Expression<Func<TSrc,bool>> srcExp)
{
    ParameterExpression destPE = Expression.Parameter(typeof(TDest));

    ExpressionConverter ec = new ExpressionConverter(typeof(TSrc),destPE);
    Expression body = ec.Visit(srcExp.Body);
    return Expression.Lambda<Func<TDest,bool>>(body,destPE);
} 

public class ExpressionConverter: ExpressionVisitor{

    private Type srcType;
    private ParameterExpression destParameter;

    public ExpressionConverter(Type src, ParameterExpression dest){
        this.srcType = src;
        this.destParameter= dest;
    } 

    protected override Expression 
       VisitParameter(ParameterExpression node)
    {
        if(node.Type == srcType)
            return this.destParameter;
        return base.VisitParameter(node);
    }
}

答案 1 :(得分:0)

我假设您需要向Entity Framework(或其他一些查询提供程序)发出这些查询。在这种情况下,您需要使用表达式而不仅仅是函数,因为只有前者存储了提供者需要转换的查询信息(例如,存储到SQL查询中)。

这是一个简单的例子:

Expression<Func<DepartmentViewModel, bool>> filterDVM = dvm => dvm.Name == "abc";

您首先需要一些接受Department并将其转换为DepartmentViewModel的逻辑:

Expression<Func<Department, DepartmentViewModel>> getViewModel = dep => 
    new DepartmentViewModel
    {
        Name = dep.Name,
        Location = dep.Location,
    };

完成此操作后,您可以将转换应用到IQueryable<Department>序列,之后,您可以应用过滤器:

var dvm = context.Departments.Select(getViewModel).Where(filterDVM);