![](/img/trans.png)
[英]Using ExpressionVisitor to modify expression for automatic translations
[英]Remove a condition from an expression using an ExpressionVisitor
我正在尝试使用定义良好的模型为定义良好的Web API构建LINQ提供程序。 我正在关注这些演练:
我已经能够创建查询提供程序,将表达式转换为所需的URL,它工作得很好。
现在这是我无法弄清楚的下一步。 想象一下,其中一个请求返回一个如下定义的对象:
[JsonObject]
public class SomeObject
{
[JsonProperty(PropertyName = "id")]
public string Id {get;set;}
[JsonProperty(PropertyName = "name")]
public string Name {get;set;}
[JsonProperty(PropertyName = "is_active")]
public bool IsActive {get;set;}
public string SomeOtherObjectId {get;set;}
}
现在您可以看到SomeOtherObjectId未使用JsonProperty属性进行修饰,这是因为它不是返回的对象定义的一部分,但它是必需的,因为它是get请求所依赖的参数。 这意味着表达式如下:
Expression<Func<SomeObject, bool>> exp = o => o.SomeOtherObjectId == "someId" && o.IsActive;
被翻译成如下:
blablabla / someId / ....
现在Web API搜索受限于他们期望的参数,因此IsActive过滤器将被忽略所以我认为在收到响应后我可以在LINQ to Objects查询中使用相同的表达式作为谓词,所以其余的过滤器都是考虑到但是为了这样做,我将不得不重新创建没有ProjectId过滤器的表达式,因为它在返回的JSON中不存在被反序列化到对象中,所以它必须变成类似于:
Expression<Func<SomeObject, bool>> modifiedExp = o => o.IsActive;
那么我可以做点什么
return deserializedObject.Where(modifiedExp);
我一直在寻找如何使用ExpressionVisitor执行此操作的示例,但我无法理解如何在没有我想要删除的过滤器的情况下重新创建表达式。
谢谢您的帮助。
更新:
感谢Evk和MaKCbIMKo,因为他们的综合答案我得到了最终的解决方案,我希望它可以帮助其他人。
protected override Expression VisitBinary(BinaryExpression node)
{
if (node.NodeType != ExpressionType.Equal) return base.VisitBinary(node);
if (new[] { node.Left, node.Right }
.Select(child => child as MemberExpression)
.Any(memberEx => memberEx != null && memberEx.Member.CustomAttributes.All(p => p.AttributeType.Name != "JsonPropertyAttribute")))
{
return Expression.Constant(true);
}
return base.VisitBinary(node);
}
这取决于表达式树的复杂程度,但在大多数情况下,您可以这样做:
class Visitor : ExpressionVisitor {
protected override Expression VisitBinary(BinaryExpression node) {
// SomeOtherObjectId == "someId"
if (node.NodeType == ExpressionType.Equal) {
foreach (var child in new[] {node.Left, node.Right}) {
var memberEx = child as MemberExpression;
if (memberEx != null && memberEx.Member.Name == "SomeOtherObjectId") {
// return True constant
return Expression.Constant(true);
}
}
}
return base.VisitBinary(node);
}
}
假设您的“SomeOtherObjectId ==”someId“”表达式位于某个“和”链上,因此您只需将其替换为“true”即可消除其效果。
然后你做:
var anotherExp = (Expression<Func<SomeObject, bool>>) new Visitor().Visit(exp);
如果你的表达式可能更复杂 - 这个例子应该让你知道如何处理它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.