Reflection mediante dynamic

Al Supporto Tecnico ci prepariamo in anticipo alle richieste sui prodotti attualmente in beta, i quali arriveranno nei prossimi mesi. Studiando Visual C# 2010 Beta 1 e le nuove feature introdotte nella runtime, ho notato che gli sviluppatori di applicazioni hanno a disposizione un nuova keyword, dynamic, che si basa sulla DLR, Dynamic Language Runtime.

Per la definizione formale e per come il compilatore si comporta durante la fase di compile-time vi rimando alla documentazione on-line che sicuramente esprime questi concetti teorici in modo più chiaro di quanto possa fare io. Open-mouthed

Quel che m’interessa descrivere è l’impatto che questo nuovo costrutto ha sulla Reflection, in particolare su come si sia notevolmente semplificata la scrittura del codice. A tal fine ripercorriamo rapidamente come funzionava la reflection sino alla versione 3.5 della runtime.

Uno sviluppatore doveva interagire con la DLL che definisce il tipo interessato e successivamente invocare le funzioni implementate nella classe tramite InvokeMember. Questo rendeva la stesura del codice sicuramente più articolata di una normale invocazione di funzione, costringendo lo sviluppatore a distinguere tra le istanze realizzate mediante Reflection e le istanze “tradizionali”.

Vediamo di seguito il seguente codice che definisce la libreria ClassLibrary:

 namespace ClassLibrary
{
    public class MyMath
    {
        public  long sum(int x, int y)
        {
            return x + y;
        }
    }
}

Ecco cosa accadeva nelle vecchie edizioni della runtime:

 class Program
{
    static void Main(string[] args)
    {
        Assembly myLibrary = null;
        try
        {
            // Carico la Libreria interessata
            myLibrary = Assembly.LoadFrom("C:\\ClassLibrary.dll");
            // Reperisco la classe con cui interagire
            Type MyMathType = myLibrary.GetType("ClassLibrary.MyMath");
            // Creo un'istanza della classe tramite reflection
            Object MyMathObj = Activator.CreateInstance(MyMathType);
            // Preparo gli argomenti da passare alla funzione
            Object[] methodArgs = new Object[2];
            methodArgs[0] = 2;
            methodArgs[1] = 3;
            // Invoco il  metodo sum indicando l'istanza, i parametri in ingresso ed i flag opportuni
            Console.WriteLine("The sum of 3 + 2 is " + 
                                MyMathType.InvokeMember("sum", BindingFlags.Default | BindingFlags.InvokeMethod,
                                null, MyMathObj, methodArgs).ToString());
        }
        catch(Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        Console.ReadLine();
    }
}

Con i tipi dynamic la stesura di codice mediante la tecnica della reflection è praticamente identica all’invocazione di un metodo per una normale istanza:

 namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //Carico la dll interessata definendo un’istanza    
            dynamic test = Assembly.LoadFrom("C:\\ClassLibrary.dll").CreateInstance("ClassLibrary.MyMath");
            // invoco il metodo tramite reflection, in modo del tutto trasperante
            Console.WriteLine("La somma di 3+2 =" + test.sum(3, 2));
            Console.ReadLine();
        }
    }
}

Non ci siamo notevolmente semplificati la vita? Smile

Carmelo Pulvirenti
Support Engineer
Windows Mobile & Embedded Developer Support
.NET & Visual Studio Technology