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 ;-)
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- LINQ, lazy loading e architettura, l'11 marzo 2011 alle 18:42
- MetadataDiffViewer: aggiornato al .NET Framework 4.0, Silverlight 4.0 e Sharepoint 2010, il 7 gennaio 2010 alle 13:58
- .NET Framework 4.0 beta 1: Windows Communication Foundation, il 18 maggio 2009 alle 16:00
- Parallelizzare in Silverlight 2.0, il 21 aprile 2009 alle 00:25
- Silverlight: performance dell'isolated storage, il 16 aprile 2009 alle 17:38
- MetadataDiffViewer: differenze tra i framework, il 15 aprile 2009 alle 18:56