In un recente progetto mi è capitato di dover generare un filtro per una query Linq dinamicamente da codice, in particolare, avevo a disposizione un metodo che accettava come parametro una Expression ma la classe T era di tipo "Entity" e non un'implementazione del "MioOggettoBase", quindi non aveva nel modello la proprietà che intendevo usare nell'expression.
Nel dettaglio: l'applicazione era in Silverlight ed avevo un ViewModelBase dove T : Entity, quindi il relativo DataContext si aspettava una query su T, il che tutto funziona se siamo all'implementazione reale dove specifico il tipo di T, ad esempio "Cliente, Pratica etc..." ossia classi del mio modello...in poche parole:
dovevo generare una lambda del tipo: (x => x.ID == 1234) senza avere dall'intellisense quella proprietà "Id".
Se non ricordo male, con le ultime versioni di Silverlight e RiaServices è possibile specificare una classe base custom e probabilmente non avrei avuto questi problemi, ma al tempo non potevo farlo, quindi mi sono scritto un piccolo metodo che mi genera proprio quella Lambda da codice, ovvero l'ExpressionTree equivalente, ricevendo l'Id numerico come parametro :
private Expression<Funcbool>> GetIDExpression(int id)
{
//--- genero dinamicamente il filtro "(x=> x.ID == id)"
ParameterExpression x = Expression.Parameter(typeof(T), "x");
Expression prop = Expression.PropertyOrField(x, "ID");
ConstantExpression val = Expression.Constant(id, typeof(int));
BinaryExpression uguale = Expression.Equal(prop, val);
Expression<Funcbool>> filtro = Expression.Lambda<Funcbool>>(uguale, new ParameterExpression[] { x });
return filtro;
}
Questo è un esempio banale, all'aumentare della complessita dell'ExpressionTree da generare le righe di codice aumentano parecchio, e soprattutto non è così intuitivo avere sott'occhio tutto questa pappardella di oggetti, legati tramite l'operatore etc.
Sicuramente è sempre utile sapere che è possibile farlo, soprattutto quando avete già in piedi una bella architettura e non volete toccarla per queste piccole eccezioni.
Lascio qui qualche link per approfondire l'argomento:
http://msdn.microsoft.com/en-us/library/bb397951.aspx
http://www.albahari.com/nutshell/predicatebuilder.aspx
http://channel9.msdn.com/Events/DevDays/DevDays-2011-Netherlands/Devdays097
http://blogs.msdn.com/b/csharpfaq/archive/tags/expression+trees/default.aspx
http://marlongrech.wordpress.com/2008/01/08/working-with-expression-trees-part-1/