在互联网的某个地方,我发现下面的课程用于将Expression<Func<T, bool>>
从DTO转换为域名:
public class EvaluateVariableVisitor<TEntity, TDto> : ExpressionVisitor
{
private readonly ParameterExpression _dtoParameter;
private readonly ParameterExpression _entityParameter;
private readonly IMapper _mapper;
public EvaluateVariableVisitor()
{
_entityParameter = Expression.Parameter(typeof(TEntity));
_dtoParameter = Expression.Parameter(typeof(TDto));
_mapper = AutoMapperConfig.Initialize();
}
protected override Expression VisitMember(MemberExpression node)
{
try
{
//change dto to entity type.
if (node.Expression.Type == _dtoParameter.Type)
{
var reducedExpression = Visit(node.Expression);
//TypeMap typeMap = Mapper.Configuration.FindTypeMapFor<TDto, TEntity>();
TypeMap typeMap = _mapper.ConfigurationProvider.FindTypeMapFor<TDto, TEntity>();
//find the correct name of the property in the destination object by using the name of the source objekt
string destinationPropertyName = typeMap.GetPropertyMaps() //GetCustomPropertyMaps()
.Where(propertyMap => propertyMap.SourceMember.Name == node.Member.Name)
.Select(propertyMap => propertyMap.DestinationProperty.Name).FirstOrDefault();
//find the correct name of the property in the destination object by using the name of the source objekt
//string destinationPropertyName = typeMap.GetPropertyMaps() //GetCustomPropertyMaps()
// .Where(propertyMap => propertyMap.SourceMember.Name == node.Member.Name)
// .Select(propertyMap => propertyMap.DestinationProperty.Name).Single();
var newMember = _entityParameter.Type.GetMember(destinationPropertyName).First();
return Expression.MakeMemberAccess(reducedExpression, newMember);
}
//Recurse down to see if we can simplify...
var expression = Visit(node.Expression);
//If we've ended up with a constant, and it's a property or a field,
//we can simplify ourselves to a constant
var constantExpression = expression as ConstantExpression;
if (constantExpression != null)
{
object container = constantExpression.Value;
object value = null;
var memberAsFieldInfo = node.Member as FieldInfo;
var memberAsPropertyInfo = node.Member as PropertyInfo;
if (memberAsFieldInfo != null)
{
value = memberAsFieldInfo.GetValue(container);
}
if (memberAsPropertyInfo != null)
{
value = memberAsPropertyInfo.GetValue(container, null);
}
if (value != null)
{
return Expression.Constant(value);
}
}
return base.VisitMember(node);
}
catch (System.Exception exc)
{
var ex = exc.Message;
throw;
}
}
//change type from dto to entity --> otherwise the generated expression tree would throw an exception, because of missmatching types(Dto can't be used in Entity expression).
protected override Expression VisitParameter(ParameterExpression node)
{
return node.Type == _dtoParameter.Type ? _entityParameter : node;
}
}
它工作得很好,但是当我在DTO中拥有相同类型的属性时,我遇到了一个问题:
public class InventoryApplicationDto
{
public int Id { get; set; }
public string Name{ get; set; }
public InventoryApplicationDto ParentApplication { get; set; }
}
首先,我必须改变:
string destinationPropertyName = typeMap.GetPropertyMaps()
.Where(propertyMap => propertyMap.SourceMember.Name == node.Member.Name)
.Select(propertyMap => propertyMap.DestinationProperty.Name).Single();
要:
string destinationPropertyName = typeMap.GetPropertyMaps()
.Where(propertyMap => propertyMap.SourceMember.Name == node.Member.Name)
.Select(propertyMap => propertyMap.DestinationProperty.Name).FirstOrDefault();
我的问题是我收到错误:
System.ArgumentException:未为类型定义属性“Int32 ID” 'InventoryApplicationDto'
在线:
return Expression.MakeMemberAccess(reducedExpression, newMember);
MakeMemberAccess方法区分大小写还是存在其他问题?