gpt4 book ai didi

c# - 表达式树 Null VisitMember

转载 作者:太空宇宙 更新时间:2023-11-03 13:11:32 24 4
gpt4 key购买 nike

我正在转换 Expression<T, bool>Expression<Y, bool>其中 T 和 Y 是不同的实体,除了通过 Automapper 映射之外,没有任何关联。本质上,我有一个我的代码使用的模型对象:

public class Store
{
public string StoreId { get; set; }

public string Name { get; set; }

public List<Phone> Phones { get; set; }

public Address Address { get; set; }

public Account Account { get; set; }

public Status Status { get; set; }
}

我正在映射到一个实体对象以存储在我的 mongo 数据库中:

public class Store : MongoEntity
{

public string AccountId { get; set; }

public string Name { get; set; }

public List<string> UserIds { get; set; }

public List<Phone> PhoneNumbers { get; set; }

public Address Address { get; set; }
}

public abstract class MongoEntity : IMongoEntity
{
[BsonId]
public ObjectId Id { get; set; }

public Status Status { get; set; }
}

我使用这个问题的答案来计算如何在表达式 ( Question ) 之间进行转换,这使我达到了 90%。我能够修改代码以获取模型存储和实体存储之间的 AutoMapper 映射,并从源属性中获取目标属性:

    private Expression<Func<TNewTarget, bool>> TransformPredicateLambda<TOldTarget, TNewTarget>(
Expression<Func<TOldTarget, bool>> predicate)
{
var lambda = (LambdaExpression)predicate;
if (lambda == null)
{
throw new NotSupportedException();
}

//Modified here to get automapper mappings
var maps = Mapper.FindTypeMapFor<TOldTarget, TNewTarget>();
var mutator = new ExpressionTargetTypeMutator(t => typeof(TNewTarget), maps);
var explorer = new ExpressionTreeExplorer();
var converted = mutator.Visit(predicate.Body);

return Expression.Lambda<Func<TNewTarget, bool>>(
converted,
lambda.Name,
lambda.TailCall,
explorer.Explore(converted).OfType<ParameterExpression>());
}

protected override Expression VisitMember(MemberExpression node)
{
var dataContractType = node.Member.ReflectedType;
var activeRecordType = _typeConverter(dataContractType);

PropertyMap prop = null;
foreach (var propertyMap in _maps)
{
var source = propertyMap.SourceMember;
var dest = propertyMap.DestinationProperty;

if (source != null && source.Name == node.Member.Name)
{
prop = propertyMap;
}
}
if (prop == null)
{
return base.VisitMember(node);
}

var propertyName = prop.DestinationProperty.Name;

var property = activeRecordType.GetProperty(propertyName);

var converted = Expression.MakeMemberAccess(
base.Visit(node.Expression),
property
);

return converted;


}

问题是,我的实体对象并不具有与模型对象相同的所有属性(例如,Account 对象与 AccountId)。当 Transformer 到达 Model 对象的 Account 属性时,我得到一个异常(因为我的 Entity 对象上没有匹配的属性)。我不能从 VisitMember 返回 null,也不允许使用 new Expression()。我如何处理忽略我的模型对象上不存在于我的实体对象上的属性?

使用评论中的信息更新

所以,为了更清楚一点,我正在使用 Automapper 从 Models.Store 映射到 Entity.Store。我的 entity.Store 只有一个 AccountId(因为我不想复制所有帐户数据),但我的 Models.Store 需要整个帐户对象(我可以通过查询帐户集合获得)。

Automapper 基本上将我的 Account 对象转换为我实体上的一个 AccountId。因此,当我搜索 x => x.Account.AccountId == abcd1234 时(其中 x 是 models.Store),我需要将表达式转换为 x => x.AccountId == abcd1234 (其中 x 是 Entity.Store)。

我有那部分工作(将 mS => mS.Account.AccountId == 1234 更改为 mE => mE.AccountId == 1234 )。我现在遇到的问题是,在执行 AccountId 属性后,以 Account 作为节点调用 VisitMember。由于我的 Entity.Store 对象中没有帐户,因此出现异常。

最佳答案

如果没有可测试/可运行的代码,就很难测试解决方案。但这是一个猜测

给定以下表达式 mS => mS.Account.AccountId == 1234 并希望转换 MemberExpressions,您将收到以下调用:

  1. VisitMember(mS.Account.AccountId
  2. VisitMember(mS.Account)

您想将第二个转换为 mE.AccountId。这涉及两个转换:一是将属性访问从 (EntityType).(AccountType).AccountId 更改为 (MongoStoreType).AccountId,同时更改底层对象。如果您已经在 ExpressionVisitor 的其他方法(可能是 VisitParameterVisitLambda)中处理参数转换,那您就没问题了。然后,您只需跳过查看父级 MemberAccess,直接跳转到祖父级:

        var converted = Expression.MakeMemberAccess(
base.Visit(node.Expression),
property
);

return converted;

变成这样:

        var parentMember = node.Expression as MemberExpression;

if (parentMember != null)
{
var grandparent = parentMember.Expression;

var converted = Expression.MakeMemberAccess(
base.Visit(grandparent),
property
);

return converted;
}
else
{
var converted = Expression.MakeMemberAccess(
base.Visit(node.Expression),
property
);

return converted;
}

关于c# - 表达式树 Null VisitMember,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28386978/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com