【发布时间】:2016-04-21 03:02:35
【问题描述】:
我正在尝试使用定义良好的模型为定义良好的 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);
}
【问题讨论】:
-
您需要知道如何在一般情况下执行此操作,或者仅针对您提供的具体表达式 (o.SomeOtherObjectId == "someId" && o.IsActive)?
-
@Evk - 在这种情况下,如果 ParameterName == "SomeOtherObjectId" 它应该从现有表达式中删除,而其余部分保持不变,无论表达式看起来如何。我不确定这是否能回答您的问题。