Le novità di C# 4.0

di: Matteo Baglini     03 Marzo 2010

Il binding di un oggetto dinamico

Una volta impostato il tipo come dynamic non ci dobbiamo più preoccupare di quale sia la sua origine, il codice sarà eseguito in modi diversi in base alla natura dell'oggetto stesso. In questo caso infatti non si parla di typing ma di binding, il tipo dipenderà proprio dall'oggetto che sarà collegato alla nostra variabile

L'esecuzione di una operazione dinamica comincia con la fase di runtime lookup: il run-time ispeziona l'oggetto interessato e successivamente delega l'invocazione ad uno specifico componente. Per esempio se stiamo lavorando con un oggetto .NET, come nel primo esempio, il componente invocato utilizzerà la Reflection per effettuare l'operazione. Diversamente, se stiamo lavorando con un oggetto COM, l'operazione sarà delegata ad un componente che effettuerà l'operazione dinamica tramite l'interfaccia IDispatch.

Se stiamo interoperando con un oggetto di un altro ambiente, prettamente dinamico come Python, verrà utilizzato uno specifico componente che eseguirà le operazioni sfruttando il Dynamic Language Runtime (DLR). Questi componenti scelti ed invocati a run-time si chiamano "binder".

Figura 1. Binder

Binder

IDynamicMetaObjectProvider

Possiamo sviluppare un nostro binder creando una classe che implementi l'interfaccia IDynamicMetaObjectProvider o più semplicemente eredita dalla classe base DynamicObject ed effettua l'override dei metodi interessati.

All'interno del .NET Framework 4.0 troveremo anche un altro oggetto che implementa l'interfaccia IDynamicMetaObjectProvider, l'ExpandoObject. Questo tipo rappresenta un oggetto i cui membri possono essere dinamicamente aggiunti o rimossi in fase di esecuzione. Prima di descrivere dettagliatamente l'ExpandoObject analizziamo il seguente frammento di codice.

var obj = new Dictionary();
obj["Name"] = "Matteo Baglini";
obj["Print"] = new Action(p => Console.WriteLine("Nome: {0}",p));

(obj["Print"] as Action)(obj["Name"]);

Sfruttando un Dictionary, con chiave di tipo string e valore di tipo object, creiamo un oggetto al quale possiamo aggiungere o rimuovere un qualsiasi elemento, quindi da un certo punto di vista, dinamico.

Naturalmente il codice di esempio porta degli svantaggi: è difficile da leggere, non permette il supporto dell'IntelliSense e se viene richiesto un elemento non presente ottengo una eccezione. Grazie ad ExpandoObject posso riscrivere il codice precedente in modo che sia più leggibile, vediamo come.

dynamic obj = new ExpandoObject();
obj.Name = "Matteo Baglini";
obj.Print = new Action<object>(p => Console.WriteLine("Nome: {0}", p));

obj.Print(obj.Name);

I passi fondamentali sono due: creare una istanza di ExpandObject e dichiararlo come dynamic. Il risultato sarà un oggetto dinamico estremamente flessibile e costruito a runtime. Possiamo aggiungere membri di ogni genere, anche eventi, come nel seguente esempio.

//inizializzo l'evento
obj.MyEvent = null;
//aggancio un handler
obj.MyEvent += new EventHandler((sender, e) => Console.WriteLine("Evento intercettato!")); ;
//scateno l'evento
if (obj.MyEvent != null)
    obj.MyEvent(obj, EventArgs.Empty);

A questo punto come aggiungere membri dovrebbe essere chiaro, la domanda che sorge spontanea è: come faccio a rimuovere un membro? La risposta è più semplice di quello che possiamo immaginare. La classe ExpandoObject implementa anche l'interfaccia IDictionary<string,object> la quale ci permette di accedere ai membri come abbiamo visto nell'esempio introduttivo oppure iterare su di essi.

foreach (var property in (IDictionary) obj)
    Console.WriteLine(property.Key + ": " + property.Value);

((IDictionary)obj).Remove("Print");

Nel precedente esempio vengono stampati a Console tutti i membri dell'istanza obj ed infine viene rimosso il metodo Print.

Ma non finisce qui. ExpandObject è adatta anche in scenari di databinding, perché implementa l'apposita interfaccia INotifyPropertyChanged, che ci notifica, grazie all'evento PropertyChanged, quando il valore di un membro è stato modificato.

((INotifyPropertyChanged) obj).PropertyChanged += 
       new PropertyChangedEventHandler(
         (sender, e) => Console.WriteLine("{0}", e.PropertyName)
       );

obj.Name = "Mario Bianchi";

Anche in questo caso l'unica accorgimento è quello di effettuare la conversione esplicita all'interfaccia desiderata.

Guide ASP.Net

Guida Windows Azure Code Snippets

Le migliori pratiche per far girare le applicazioni "in the cloud",...

Guida ASP.NET MVC Best Practices

Un workflow dettagliato e ricco di suggerimenti pratici per...

Guida ASP.NET Starter Kit

Un modo semplice per imparare ad utilizzare le tecnologie Microsoft...

Altre guide

Newsletter @Microsoft Dev

Ogni giovedì, direttamente nella tua e-mail: articoli, guide, tutorial e script ASP, ASP.Net, SQL server e IIS.

Iscriviti alla newsletter

Altre newsletter

Corsi in aula

Corso Progettazione database

11 Maggio 2012 a Milano
Disponibilità: 6 Posti

Amministratore di Reti Windows Server 2008

11 Giugno 2012 a Milano
Disponibilità: 5 Posti

Nessun corso previsto