Sto provando a creare un provider LINQ su un'API Web ben definita con un modello ben definito. Sto seguendo queste procedure dettagliate:Rimuovere una condizione da un'espressione utilizzando un ExpressionVisitor
sono stato in grado di creare il provider di query che traduce l'espressione per l'URL desiderato e funziona abbastanza bene.
Ora ecco il prossimo passo che non riesco proprio a capire. Immaginate che una delle richieste restituisce un oggetto definito in questo modo:
[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;}
}
Ora, come si può vedere la SomeOtherObjectId non è decorato con l'attributo JsonProperty, cioè perché non è parte della definizione dell'oggetto restituito, ma è necessario perché è il parametro da cui dipende la richiesta get. Ciò significa che un'espressione come la seguente:
Expression<Func<SomeObject, bool>> exp = o => o.SomeOtherObjectId == "someId" && o.IsActive;
è tradotto in qualcosa di simile:
blablabla/QualcheID/....
Ora le ricerche web API sono limitati a i parametri che si aspettano in modo che il filtro IsActive venga ignorato, quindi ho pensato che dopo aver ricevuto la risposta potrei usare la stessa espressione di un predicato in una query LINQ to Objects in modo che il resto dei filtri sia preso in considerazione ma per fare così avrei voluto per ricreare l'espressione senza il filtro ProjectID in quanto non esiste nel JSON restituita che viene deserializzato in oggetto, in modo che avrebbe dovuto diventare qualcosa di simile:
Expression<Func<SomeObject, bool>> modifiedExp = o => o.IsActive;
Allora posso fare qualcosa di simile
return deserializedObject.Where(modifiedExp);
Sono stato alla ricerca di esempi su come farlo utilizzando un ExpressionVisitor ma non riesco proprio a capire come ricreare l'espressione senza il filtro che voglio rimosso.
Grazie per il vostro aiuto.
UPDATE:
Grazie ad entrambi Evk e MaKCbIMKo dal momento che con le loro risposte combinate ho avuto la soluzione finale, che io includo nella speranza che possa aiutare gli altri.
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);
}
È necessario sapere come farlo nel caso generico o solo per l'espressione concreta fornita (o.SomeOtherObjectId == "someId" && o.IsActive)? – Evk
@Evk: in questo caso se ParameterName == "SomeOtherObjectId" deve essere rimosso dall'espressione esistente lasciando il resto invariato, indipendentemente dall'aspetto dell'espressione. Non sono sicuro se questo risponda alla tua domanda. –