Preso da LINQ, Expression e compagnia bella, mi è venuto in mente di provare ad applicare LINQ anche in WPF, la mia primissima passione. Ho pensato al Binding, che è bellissimo, ma spesso mi trovo a dover usare converter che, anche se molto stupidi, richiedono di creare una classe che implementi IValueConverter, referenziarla e instanziarla nel markup.
Ho creato quindi una MarkupExtension personalizzata che imposti in fase di inizializzazione un converter basato su espressioni inserite direttamente nel markup. Partiamo quindi dalla fine; l'utilizzo è il seguente e permette di mettere in maiuscolo ciò che è stato immesso nella TextBox txt:
<TextBox x:Name="txt" Text="Testo" /> <TextBlock Text="{Binding Path=Text,ElementName=txt, Converter={m:Expression value.ToString().ToUpper(culture)}}" />
Creare una MarkupExtension è abbastanza semplice. Basta ereditare dalla classe e implementare ProvideValue, chiamato in fase di inizializzazione del markup. La mia implementazione effettua il parsing dell'espressione, ottiene un delegate e la passa ad una nuova istanza di una mia ExpressionValueConverter che implementa IValueConverter e semplicemente chiama questo delegate:
public delegate object ExpressionConverterDelegate(object value, object target, Type targetType, object parameter, CultureInfo culture);
Il parsing dell'espressione l'ho poi affidato ad una serie di classi contenute nell'esempio DynamicLinq presente nel SDK del .NET Framework 3.5. Fatte alcune piccole modifiche, chiamando DynamicExpression.ParseLambda possiamo ottenere una lambda expression, in questo caso con la nostra firma, da poter compilare così da ottenere il delegate:
public override object ProvideValue(IServiceProvider serviceProvider) { IProvideValueTarget provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); LambdaExpression le = DynamicExpression.ParseLambda<ExpressionConverterDelegate>( new ParameterExpression[] { Expression.Parameter(typeof(object), "value"), Expression.Parameter(typeof(object), "target"), Expression.Parameter(typeof(Type), "targetType"), Expression.Parameter(typeof(object), "parameter"), Expression.Parameter(typeof(CultureInfo), "culture") }, typeof(object), this.ConvertExpression, null); ExpressionConverterDelegate converter = (ExpressionConverterDelegate)le.Compile(); return new ExpressionValueConverter(provideValueTarget.TargetObject, converter); }
Figo no? Le performance poi una volta creato il delegate sono le medesime di una normale classe.
Qui il codice sorgente.
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- Dettagli sul metodo SelectDTO, il 26 aprile 2009 alle 13:58
- LINQ to Reflection - Parte tre, il 20 aprile 2009 alle 07:08
- Abusi della parola chiave var e poca leggibilità dei generics, il 29 agosto 2008 alle 13:10
- LINQ to reflection - Parte due, il 23 luglio 2008 alle 14:26
- Eccovi LINQ to reflection, il 19 luglio 2008 alle 21:17