Próbuję zbudować dostawcę LINQ do dobrze zdefiniowanego interfejsu API sieci Web z dobrze zdefiniowanym modelem. Śledzę te instruktaże:Usuwanie warunku z wyrażenia za pomocą ExpressionVisitor
udało mi się stworzyć Provider kwerendę, która przekłada się na żądany wyraz URL i działa całkiem dobrze.
Oto kolejny krok, którego nie mogę pojąć. Wyobraźmy sobie, że jeden z wniosków zwraca obiekt zdefiniowany następująco:
[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;}
}
Teraz jak widać SomeOtherObjectId nie jest ozdobiony atrybutu JsonProperty, to dlatego, że nie jest częścią zwróconej definicji obiektu, ale jest potrzebne, ponieważ jest to parametr, od którego zależy żądanie pobierania. Oznacza to, że wyraz tak:
Expression<Func<SomeObject, bool>> exp = o => o.SomeOtherObjectId == "someId" && o.IsActive;
przekłada się na coś takiego:
blablabla/someId/....
Teraz wyszukiwania Web API są ograniczone parametry, których oczekują, więc filtr IsActive zostanie zignorowany, więc uznałem, że po otrzymaniu odpowiedzi mogę użyć tego samego wyrażenia co predykat w kwerendzie LINQ do Objects, więc pozostałe filtry są brane pod uwagę, ale w celu wykonania więc musiałbym odtworzyć wyraz bez filtra ProjectID ponieważ nie istnieje w zwróconym JSON, który pobiera rozszeregować do obiektu, więc będzie musiała stać się coś takiego:
Expression<Func<SomeObject, bool>> modifiedExp = o => o.IsActive;
Więc mogę zrobić coś takiego
return deserializedObject.Where(modifiedExp);
Szukałem przykładów tego, jak to zrobić za pomocą ExpressionVisitor, ale po prostu nie mogę zrozumieć, jak odtworzyć wyrażenie bez filtra, który chcę usunąć.
Dziękuję za pomoc.
UPDATE:
Dziękuję zarówno Evk i MaKCbIMKo ponieważ z ich łączna odpowiedzi dostałem ostateczne rozwiązanie, które mam w tym w nadziei, że może pomóc innym.
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);
}
Musisz wiedzieć, jak to zrobić w ogólnym przypadku lub po prostu dla konkretnego wyrażenia, które podałeś (o.SomeOtherObjectId == "someId" && o.IsActive)? – Evk
@Evk - W tym przypadku, jeśli parametr ParameterName == "SomeOtherObjectId" powinien zostać usunięty z istniejącego wyrażenia, pozostawiając resztę bez zmian, niezależnie od tego, jak będzie wyglądać wyrażenie. Nie jestem pewien, czy to odpowiedź na twoje pytanie. –