testa
 
 
 
Internet Reflection
cornice di chiusura
 
Comprendere la Reflection
 
Utilizzando i servizi di Reflection, si è in grado di ottenere programmaticamente le stesse informazioni METADATA visualizzate mediante ildasm.exe, utilizzando anche un modello più semplice.
Per esempio grazie alla Reflection è possibile ottenere un elenco di tutti i tipi contenuti in una data .DLL o .EXE, comprensivo di metodi, campi, proprietà ed eventi definiti da un dato type. Si può dinamicamente scoprire l'elenco di interface supportate da un dato type, i parametri dei metodi ed altri dati (classi base, informazioni sui namespaces, manifest data e così via).

Come tutti i namespace, System.Reflection contiene dei type relativi (Assembly, AssemblyName, EventInfo, FieldInfo, MemberInfo, MethodInfo, Module, ParameterInfo, PropertyInfo).
La classe System.Type
 
La class System.Type definisce dei membri che possono essere utilizzati per esaminare un type's metadata, molti dei quali ritornato dei type derivati dal namespace System.Reflection.
Per esempio
  • Type.GetMethods() ritorna un array di oggetti MethodInfo
  • Type.GetFields() ritorna un array di oggetti FieldInfo
  • ...
  • le seguenti proprietà permetto di scoprire alcune caratteristiche del Type che si sta analizzando (ad esempio se è un'entità astratta, un array, una class nidificata e così via...)
  • Type.IsAbstract
  • Type.IsArray
  • Type.IsClass
  • Type.IsCOMObject
  • Type.IsEnum
  • Type.IsGenericTypeDefinition
  • Type.IsGenericParameter
  • Type.IsInterface
  • Type.IsPrimitive
  • Type.IsNestedPrivate
  • Type.IsNestedPublic
  • Type.IsSealed
  • Type.IsValueType
  • ...
  • i metodi seguenti permettono di ottenere un array rappresentante gli item (interface, metodi, proprietà, ecc..) di cui sta richiedendo. Ogni metodo ritorna un array di oggetti relativi. Attenzione che ciascuno di questi metodi ha anche la sua forma al singolare che permette di ottenere uno specifico oggetto dal nome, invece di un array di oggetti.
  • Type.GetConstructors()
  • Type.GetEvents()
  • Type.GetInterfaces()
  • Type.GetMembers()
  • Type.GetNestedTypes()
  • Type.GetProperties()
  • Type.FindMembers()
  • Type.GetType()
  • Type.InvokeMember()
Late Binding
 
Late Binding è una tecnica grazie alla quale è possibile caricare un'istanza di un certo TYPE ed invocarne i metodi (at runtime, durante l'esecuzione), senza aver completa conoscenza della sua forma ed esistenza.

Quando si sviluppa un'applicazione che ASSOCIA DOPO (late bind) ad un TYPE di un assembly esterno e non ci sono motivi per impostare la referenza all'assembly, il MANIFEST chiamante non ha alcuna relazione diretta all'assembly.

A prima vista non è facile vedere le potenzialità del LATE BINDING. L'associazione anticipata permette di rilevare errori in fase di compilazione, mentre l'associazione posteriore li rileverebbe in fase di esecuzione. Nonostante ciò il LATE BINDING ha un ruolo fondamentale nell'estensibilità delle applicazioni che si vanno a sviluppare.
 
La class System.Activator definita in mscorlib.dll è la chiave per il LATE BINDING di .NET.

 // Questo programma carica una libreria esterna
 // e crea un oggetto utilizzando il late binding
 public class Program
 {
  static void Main(string[] args)
  {
   Console.WriteLine("**** Late Binding ****");
 
   // Prova a caricare una copia locale di CarLibrary
   Assembly a = null;
 
   try
   {
    a = Assembly.Load("CarLibrary");
   }
   catch(FileNotFoundException ex)
   {
    Console.WriteLine(ex.Message);
    return;
   }
 
   if (a != null)
   {
    CreateUsingLateBinding(a);
   }
 
   Console.ReadLine();
  }
 
  static void CreateUsingLateBinding(Assembly a)
  {
   try
   {
   // Ottiene i metadata del Type MiniVan
   Type miniVan = a.GetType("CarLibrary.MiniVan");
 
   // Crea l'oggetto MiniVan on-the-fly
   object obj = Activator.CreateInstance(miniVan);
   Console.WriteLine($"Creato un { obj } utilizzando LATE BINDING!");
   }
   catch (Exception ex)
   {
    Console.WriteLine(ex.Message);
   }
  }
 }

Per eseguire questo codice bisogna caricare CarLibrary.dll nella stessa posizione dell'assembly, altrimenti utilizzare il metodo Assembly.LoadFrom() indicando il percorso completo dove trovare il file.
È importante non impostare la reference a CarLibrary.dll in Visual Studio!!!!

Il metodo Activator.CreateInstance() ritorna un oggetto System.Object piuttosto che un TYPE completo MiniVan e non è possibile creare il CAST ancipato

object obj = (MiniVan)Activator.CreateInstance(miniVan);

perchè creerebbe un errore di compilazione non avendo alcuna referenza a CarLibrary.dll!!!!
ATTENZIONE: tutto il processo di LATE BINDING si basa sul fatto che si cerca di creare l'istanza di un oggetto di cui non si ha alcuna conoscenza in fase di compilazione!
 
Invocare metodi senza parametri
Mettiamo di voler invocare il metodo TurboBoost() di MiniVan: per prima cosa si dovrà ottenere il MethodInfo del metodo TurboBoost() utilizzando Type.GetMethod(); poi si potrà chiamare MiniVan.TurboBoos() utilizzando Invoke().
MethodInfo.Invoke() necessita che vengano inviati tutti i parametri necessari per invocare il metodo indicati in MethodInfo. Questi parametri sono rappresentati da un array di oggetti System.Object.
Detto questo TurboBoost() non necessita di alcun parametro, basta passagli null:

 static void CreateUsingLateBinding(Assembly a)
 {
  // Ottengo i metadata del type MiniVan
  Type miniVan = a.GetType("CarLibrary.MiniVan");
 
  // Creo l'oggetto MiniVan on-the-fly
  object obj = Activator.CreateInstance(miniVan);
  Console.WriteLine($"Creato un { obj } utilizzando LATE BINDING!");
 
  // Ottengo le informazioni per TurboBoost
  MethodInfo mi = miniVan.GetMethod("TurboBoost");
 
  // Invoco il metodo con parametri "null"
  mi.Invoke(obj, null);
 }

A questo punto si potrà vedere il messaggio della chiamata TurboBoost.
 
Invocare metodi con parametri
Per passare i parametri al metodo Invoke, invece di passare "null", si creerà un array di object compilato con i parametri che si vogliono passare:

  mi.Invoke(obj, new object[] { param1, param2, ...});

Attributo
.NET sono class che estendono la class abstract System.Attribute. Se si consultano i namespace .NET, si troveranno numerosi attributi predefiniti che si possono utilizzare nelle applicazioni.
Inoltre si è liberi di creare i propri attributi, per definire comportamenti personalizzati, derivando da Attribute.
Eccone un breve esempio:
  • [CLSCompilant]
  • [DLLImport] permette a .NET di caricare librerie C e C++ non gestite
  • [Obsolete] rende obsoleto/deprecato un tipo o un membro. Se altri programmatori utilizzando questo oggetto, riceveranno il messaggio che esiste un nuovo oggetto che lo sostituisce, ma continua a funzionare
  • [Serializable] definisce una class o structure come "serializzabile", cioè in grado di mantenere il proprio stato durante lo stream
  • [NonSerializable] esattamente il contrario della precedente
  • [ServiceContract] definisce un metodo come contract implementato da un servizio WCF
 
Uno dei ruoli del compilatore .NET è quello di generare metadata per tutti i TYPE definiti e referenziati.

In aggiunta agli standard metadati, la piattaforma .NET fornisce, ai programmatori, un modo per includere ulteriori metadata ad un assembly, utilizzando gli Attributi
Gli Attributi
 
Per creare attributi personalizzati, si deve creare una nuova class che derivi da System.Attribute.
È buona norma, creare gli attributi personalizzati come sealed (non ereditabili).

public sealed class MyNewAttribute : System.Attribute
{
 public string Description { get; set; }
 
 public MyNewAttribute(string myDescription)
 {
  Description = myDescription;
 }
 public MyNewAttribute() {}
}

[MyNewAttribute(Description = "Named Property Syntax")]
public class AClass{}

[MyNewAttribute("Type description")]
public class BClass{}

La classe AClass utilizza la Named Property Syntax per determinare a quale proprietà determinare la descrizione.
Utilizzando questa tecnica, il costruttore associa
 
 
 
I23 di Boccaletti Emanuele
 
I23 di Boccaletti Emanuele
41121 Modena (MO)
Tel. +39 347 1302420
emanuele@i23.eu
Skype: emanuele.boccaletti
 
 
Copyright © I23 di Boccaletti Emanuele - emanuele@i23.eu