简体   繁体   English

转换复杂表达式<Func<TDTO> ,bool&gt; 到表达式<Func<TEntity> ,布尔&gt;

[英]Convert Complex Expression<Func<TDTO>,bool> to Expression<Func<TEntity>,bool>

I have DTOmodel in my Framework.我的框架中有 DTOmodel。 BLL and View do not see EntiyModel at all. BLL 和 View 根本看不到 EntiyModel。 I want to transfer and convert Complex Expression between layers.我想在层之间传输和转换复杂表达式。

this is a method in the BLL like this...这是 BLL 中的一种方法,就像这样......

//// BLL(Service)
Public PersonDTO getAll(Expression<Func<PersonDTO, bool>> whereCondition)
{

   return _repository.getAll(whereCondition);

}


// DLL(Repository)

Public PersonDTO getAll(Expression<Func<PersonDTO, bool>> whereCondition)
{

   Expression<Func<Person, bool>> NewCondition = ?/ How Convert DTOwhereCondition ???

   return DataContext.Persons(NewCondition);

}

///// I want to create complex expression on PersonDTO like this: ///// 我想像这样在 PersonDTO 上创建复杂的表达式:

var persons = serive.getPersons(i => i.PersonDetailsDTO.Count == 3);

///// My Classes ///// 我的课程

     public class Person
       {
        public Int32 Id { get; set; }
        public String FirstName { get; set; }
        public String LastName { get; set; }
        public List<PersonDetail> PersonDetails { get; set; }
       }


    public class PersonDTO
      {
        public Int32 Id { get; set; }
        public String FirstName { get; set; }
        public String LastName { get; set; }
        public List<PersonDetailDTO> PersonDetailsDTO { get; set; }
      }

This is quite the most basic solution. 这是最基本的解决方案。 If you need more features, maybe you can work your way up from there. 如果您需要更多功能,也许可以从那里继续进行。 So far it allows to optionally provide a delegate to resolve mapped property names, but the property types have to be the same. 到目前为止,它允许有选择地提供委托来解析映射的属性名称,但是属性类型必须相同。

Usage: 用法:

var mappedExpression =
    ExpressionMapper<Person>.MapFrom(originalDtoExpression, null);

// or:

var mappedExpression =
    ExpressionMapper<Person>.MapFrom(originalDtoExpression,
            entityPropertyName => someMapper.ResolveDtoPropertyName(entityPropertyName));

Implementation: 实现方式:

public class ExpressionMapper<TTarget> : ExpressionVisitor
{
    protected ExpressionMapper(Type sourceType, Func<string, string> resolveTargetMemberNameFunc)
    {
        this.SourceType = sourceType;
        this.ResolveTargetMemberNameFunc = resolveTargetMemberNameFunc ?? (cur => cur);
    }

    public Func<string, string> ResolveTargetMemberNameFunc { get; private set; }

    public Type SourceType { get; private set; }

    public static Expression MapFrom<TSource>(Expression sourceExpression, Func<string, string> resolveTargetMemberNameFunc)
    {
        return new ExpressionMapper<TTarget>(typeof(TSource), resolveTargetMemberNameFunc).Visit(sourceExpression);
    }

    public static Expression<Func<TTarget, bool>> MapFrom<TSource>(Expression<Func<TSource, bool>> sourcePredicateExpression, Func<string, string> resolveTargetMemberNameFunc)
    {
        return Expression.Lambda<Func<TTarget, bool>>(
                MapFrom<TSource>(sourcePredicateExpression.Body, resolveTargetMemberNameFunc),
                Expression.Parameter(typeof(TTarget), sourcePredicateExpression.Parameters[0].Name));
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        var sourceMemberName = node.Member.Name;
        var targetNode = this.Visit(node.Expression);
        var targetMemberName = this.ResolveTargetMemberNameFunc(sourceMemberName);
        var targetMember = targetNode.Type.GetMember(targetMemberName).FirstOrDefault();

        if (targetMember == null)
        {
            throw new NotSupportedException(String.Format("The source type '{0}' cannot be mapped to the target type '{1}', because that target type has no member '{2}'.", node.Expression.Type.Name, targetNode.Type.Name, targetMemberName));
        }

        return Expression.MakeMemberAccess(targetNode, targetMember);
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (node.Type == this.SourceType)
        {
            return Expression.Parameter(typeof(TTarget), node.Name);
        }

        return node;
    }
}

I have used AutoMapper to convert expressions using DTOs to Entities.我使用 AutoMapper 将使用 DTO 的表达式转换为实体。 Expression mapping is part of AutoMapper.Extensions.ExpressionMapping package.表达式映射是 AutoMapper.Extensions.ExpressionMapping 包的一部分。 You essentially have to call AddExpressionMapping when you call AddAutoMapper (which itself is an extension method to IServiceCollection)当您调用 AddAutoMapper(它本身是 IServiceCollection 的扩展方法)时,您本质上必须调用 AddExpressionMapping

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM