我正在尝试使用定义明确的模型为定义明确的 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);
如果您的表达式可能更复杂 - 这个示例应该让您了解如何处理它。
关于c# - 使用 ExpressionVisitor 从表达式中删除条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36746895/