2016-04-20 14 views
6

Tôi đang cố gắng xây dựng nhà cung cấp LINQ cho một API web được xác định rõ với mô hình được xác định rõ. Tôi làm theo các walkthrough:Xóa điều kiện khỏi biểu thức bằng cách sử dụng ExpressionVisitor

tôi đã có thể để tạo ra các nhà cung cấp Query biên dịch biểu thức để URL mong muốn và nó hoạt động khá tốt.

Bây giờ, đây là bước tiếp theo mà tôi không thể tìm ra. Hãy tưởng tượng rằng một trong những yêu cầu trả về một đối tượng được định nghĩa như thế này:

[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;} 
} 

Bây giờ như bạn sẽ nhìn thấy SomeOtherObjectId không được trang trí với các thuộc tính JsonProperty, đó là bởi vì nó không phải là một phần của định nghĩa đối tượng quay trở lại nhưng nó là cần thiết vì nó là tham số mà yêu cầu nhận phụ thuộc vào. Điều này có nghĩa rằng một biểu thức như sau:

Expression<Func<SomeObject, bool>> exp = o => o.SomeOtherObjectId == "someId" && o.IsActive; 

Được dịch ra tiếng gì đó như:

blablabla/someId/....

Bây giờ tìm kiếm web API được giới hạn trong các tham số mà chúng mong đợi vì vậy bộ lọc IsActive sẽ bị bỏ qua vì vậy tôi nhận thấy rằng sau khi nhận được phản hồi, tôi có thể sử dụng cùng biểu thức như một vị từ trong truy vấn LINQ to Objects để phần còn lại của bộ lọc được xem xét nhưng để thực hiện vì vậy tôi sẽ có để tái tạo các biểu hiện không có bộ lọc ProjectId vì nó không tồn tại trong JSON trở lại đó được deserialized vào đối tượng, vì vậy nó sẽ phải trở thành một cái gì đó như:

Expression<Func<SomeObject, bool>> modifiedExp = o => o.IsActive; 

Vì vậy, sau đó tôi có thể làm một cái gì đó giống như

return deserializedObject.Where(modifiedExp); 

Tôi đã tìm kiếm các ví dụ về cách thực hiện việc này bằng ExpressionVisitor nhưng tôi không thể hiểu cách tạo lại biểu thức mà không có bộ lọc tôi muốn xóa.

Cảm ơn sự giúp đỡ của bạn.

UPDATE:

Cảm ơn bạn để cả hai EvkMaKCbIMKo từ với câu trả lời của họ kết hợp Tôi có giải pháp cuối cùng mà tôi đang kể cả với hy vọng rằng nó có thể giúp đỡ người khác.

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); 
    } 
+0

Bạn cần biết cách thực hiện điều đó trong trường hợp chung hoặc chỉ cho biểu thức cụ thể mà bạn đã cung cấp (o.SomeOtherObjectId == "someId" && o.IsActive)? – Evk

+0

@Evk - Trong trường hợp này nếu ParameterName == "SomeOtherObjectId", nó sẽ bị loại bỏ khỏi biểu thức hiện tại để phần còn lại không thay đổi, bất kể biểu thức trông như thế nào. Tôi không chắc chắn nếu điều này trả lời câu hỏi của bạn. –

Trả lời

2

Nó phụ thuộc vào độ phức tạp cây biểu hiện của bạn thực sự là, nhưng trong trường hợp đơn giản nhất bạn có thể làm như thế:

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); 
    }   
} 

này giả định của bạn "SomeOtherObjectId == 'someId'" biểu thức là tại một số "và "chuỗi, vì vậy bạn chỉ cần thay thế bằng" true "để loại bỏ hiệu ứng của nó.

Sau đó, bạn làm:

var anotherExp = (Expression<Func<SomeObject, bool>>) new Visitor().Visit(exp); 

Nếu biểu hiện của bạn có thể phức tạp hơn - ví dụ này sẽ cho bạn một ý tưởng về làm thế nào để xử lý nó.

+0

Đây chính xác là những gì tôi đang tìm kiếm, tôi đã mất tích trong số những thứ khác "return Expression.Constant (true)". Cảm ơn bạn. –

2

Đây là một basic example về cách sửa đổi cây biểu thức.

Bạn sẽ cần tạo ExpressionVisitor của riêng mình và định cấu hình theo cách tìm kiếm các điều kiện sử dụng thuộc tính bạn muốn bỏ qua (ví dụ: thuộc tính Json bị thiếu hoặc thuộc tính khác).

Sau đó, chỉ cần xóa chúng khỏi cây hoặc thay bằng biểu thức 'luôn đúng' thay vì kiểm tra giá trị thuộc tính.

Ngoài ra, here bạn có thể tìm thấy thông tin hữu ích về những gì bạn đang yêu cầu.

+0

@MaKCblMKo - Thật không may tôi đã nhìn thấy các tài liệu tham khảo bạn đã đề cập nhưng vẫn còn thiếu một vài điều để có được giải pháp. 1 cho tôi ý tưởng kiểm tra thuộc tính Json thay vì tên thuộc tính mà làm cho một giải pháp tốt hơn chung chung hơn. –

Các vấn đề liên quan