[英]How to map Expression<Func<TEntity, bool>> to Expression<Func<TDbEntity, bool>>
[英]Convert Complex Expression<Func<TDTO>,bool> to Expression<Func<TEntity>,bool>
我的框架中有 DTOmodel。 BLL 和 View 根本看不到 EntiyModel。 我想在层之间传输和转换复杂表达式。
这是 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);
}
///// 我想像这样在 PersonDTO 上创建复杂的表达式:
var persons = serive.getPersons(i => i.PersonDetailsDTO.Count == 3);
///// 我的课程
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; }
}
这是最基本的解决方案。 如果您需要更多功能,也许可以从那里继续进行。 到目前为止,它允许有选择地提供委托来解析映射的属性名称,但是属性类型必须相同。
用法:
var mappedExpression =
ExpressionMapper<Person>.MapFrom(originalDtoExpression, null);
// or:
var mappedExpression =
ExpressionMapper<Person>.MapFrom(originalDtoExpression,
entityPropertyName => someMapper.ResolveDtoPropertyName(entityPropertyName));
实现方式:
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;
}
}
我使用 AutoMapper 将使用 DTO 的表达式转换为实体。 表达式映射是 AutoMapper.Extensions.ExpressionMapping 包的一部分。 当您调用 AddAutoMapper(它本身是 IServiceCollection 的扩展方法)时,您本质上必须调用 AddExpressionMapping
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.