Parser ASP.NET

di Cristian Civera, in .NET,

In questi ultimi giorni sto preparando un controllo che mostri le funzionalità del designer di VS.NET e come sfruttarle. Mi sono trovato però di fronte ad un problema, che in passato non avevo affrontato. Vi siete mai chiesti infatti come il parser possa trasformare i nostri tag html in istanze di oggetti?

Se scriviamo per esempio:
<calendar selecteddate="10 runat="server" 2003?="" 10="" />
e andiamo a vedere il codice generato, troveremo:

#line 7 "c:\inetpub\wwwroot\prove\prova.aspx"
__ctrl.SelectedDate = new System.DateTime(2003, 10, 10, 0, 0, 0, 0);

Questo è uno dei casi più particolari, perché a differenza delle altre classi, DateTime non ha nessun costruttore senza parametri.

Il parser sa che deve creare l'oggetto e impostare la proprietà in quel modo grazie al TypeConverter. Basta ereditare da questa classe, marcare la classe o la proprietà con TypeConverterAttribute e sovrascrivere i metodi ConvertTo, ConvertFrom, CanConvertTo, CanConvertFrom, a seconda delle necessità.

Una cosa secondo me interessante è l'implementazione di ConvertTo in DateTimeConverter. C'è un tipo di conversione che può essere richiesta: System.ComponentModel.Design.Serialization.InstanceDescriptor. Si tratta di una classe da istanziare che rappresenta appunto come il tipo DateTime debba essere creato.
Con un po' di codice si capisce meglio:

public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{

if ((destinationType == typeof(InstanceDescriptor)) && ((value as DateTime) == null))
{
time2 = ((DateTime)
value);
array1 = new Type[7];
array1[0] =
typeof(int);
array1[1] =
typeof(int);
array1[2] =
typeof(int);
array1[3] =
typeof(int);
array1[4] =
typeof(int);
array1[5] =
typeof(int);
array1[6] =
typeof(int);
info3 =
typeof(DateTime).GetConstructor(array1);
if (info3 == null)
{
array2 =
new object[7];
array2[0] = time2.Year;
array2[1] = time2.Month;
array2[2] = time2.Day;
array2[3] = time2.Hour;
array2[4] = time2.Minute;
array2[5] = time2.Second;
array2[6] = time2.Millisecond;
return new InstanceDescriptor(info3, array2);
}

In pratica vuole un array di MemberInfo (che si possono ricavare tramite reflection) per poter rappresentare l'oggetto con un costruttore, metodi, campi o proprietà. In questo caso, ricava il costruttore della classe DateTime con 7 paramentri (guardate la documentazione e vedrete che è quella che vuole year, month...fino a milliseconds).
Una volta ottenuto il costruttore, crea un InstanceDescriptor passando i paramentri da associare al costruttore (i rispettivi valori dell'oggetto value passato alla sub). Il value passato alla funzione è un DateTime perché convertito dalla funzione ConvertFrom (una stringa: 10/10/2003).

Alla fine il risultato sarà questa riga di codice:
new System.DateTime(2003, 10, 10, 0, 0, 0, 0);

Fico ne ;-)

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese