Scommetto che tutti voi almeno una volta vi siete chiesti come
funziona il meccanismo di Visual Studio 2005 che genera i file di codice per le
risorse e per i file di configurazione in WindowsForms ma anche i DataSet. Vi
confesso che a me ha sempre stuzzicato e spesso e volentieri ho immaginato i
vantaggi che ne avrei potuto trarre se fossi riuscito a creare un generatore
analogo.
La mia ricerca perciò è partita da quello che appariva essere
la sorgente di questi file. Se aprite le proprietà di un qualsiasi file in
Visual Studio (tutti tranne quelli di un progetto web...) vi renderete conto che
c'è una voce sempre presente. Mi riferisco a "Custom Tool". Tale voce, nel caso
dei file da cui viene generato un file sorgente contiene una stringa che a prima
vista può apparire in qualche modo legata a .NET. Purtroppo dopo una ricerca
approfondita con reflector non si riesce a trovare nulla che possa essere in
qualche modo correlato. A questo punto la mia ricerca ha preso la via di Google
e in breve sono riuscito a trovare che su gotdotnet esiste un esempio, riferito
alle precedenti versioni di Visual Studio .NET 2002/2003. Questo esempio va
sotto il nome di BaseCodeGeneratorWithSite. Si tratta di uno zip, che
contiene i progetti per le due versioni di VS.NET.
Dovete sapere infatti che questa caratteristica è presente
fin dalla prima versione dell'IDE. Addirittura nella versione 2002 le classi che
si possono scaricare da gotdotnet erano dichiarate pubbliche negli assembly
di Visual Studio ma poi sono state rese private nella versione successiva. Ecco
il motivo per cui esse sono state pubblicate sotto forma di file sorgente
nelle pagine di gotdotnet. Venendo alla versione 2005, dalle ricerche che ho effettuato
ho scoperto che alcune delle interfacce presenti nel progetto di gotdotnet sono
nuovamente esposte pubblicamente e si possono trovare nell'assembly
Microsoft.VisualStudio.Shell.Interop.dll, che si trova nella GAC.
Tuttavia, il progetto scaricato da gotdotnet, nella versione
2003, e compilato con Visual Studio 2005 fa perfettamente il proprio dovere a
testimonianza che il meccanismo di generazione non è affatto cambiato dalle
versioni precedenti. Tale meccanismo è decisamente banale e
piuttosto "grezzo" se mi passate il
termine. Credo infatti che con un minimo di impegno se ne potrebbero trarre
delle grandi soddisfazioni, ma attualmente si tratta di un sistema un po'
limitato. Ma non è il caso di demoralizzarsi. Anche così com'è si riesce a
combinare qualcosa di buono. Se vi scaricate lo zip che ho allegato troverete un
Custom Tool, che poi vi spiegherò come installare, che consente qualora specificato
su un file xml di generare le classi che operano la sua serializzazione/deserializzazione,
alla stessa stregua di quello che si fa con xsd.exe.
Un Custom Tool, altro non è che un componente COM che
implementa l'interfaccia IVsSingleFileGenerator, e in quanto tale può
benissimo essere realizzato scrivendo un po' di codice in .NET; Questa
interfaccia attualmente è esposta appunto dall'assembly che prima citavo, ma è
indubbiamente molto più comodo utilizzare le classi BaseCodeGenerator e
BaseCodeGeneratorWithSite. Alla fine realizzare un custom tool, a parte
il codice necessario per convertire il file in ciò che vogliamo, si limita alle
seguenti poche righe di codice:
[Guid("CE1B4057-D10A-4cd6-8E13-29B4699ACEAD")]
public class XmlSerializationCSharpGenerator : BaseCodeGenerator
{
public override string GetDefaultExtension()
{
return ".cs";
}
protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
{
// TODO: convertire il file qui
}
}
Il primo metodo comunica a
VisualStudio l'estensione che dovrà essere usata per il file generato. Tale file
avrà lo stesso nome di quello sorgente, salvo che l'estensione sarà cambiata e
apparirà come nidificato all'interno del file sorgente stesso. Il secondo metodo
invece, ricevuti in input il nome del file e il suo contenuto, si occupa di
generare il codice e di restituirlo sotto forma di un array di bytes che Visual
Studio si occuperà di salvare nella posizione opportuna. Ecco cosa intendo per
"limitato". in effetti con questo meccanismo è possibile creare solo un file per
ogni sorgente, e lo si può fare avendo in input esclusivamente il file sorgente.
Se si volessero passare dei parametri per customizzare l'output ad esempio,
questa possibilità ci sarà negata.
L'ultima cosa da notare nel sorgente che ho riportato è la
presenza di un GUID generato casualmente con l'apposito strumento di Visual
Studio. Tale GUID è quello che poi dovremmo utilizzare per registrare il Custom
Tool nell'IDE di VS2005. Ecco di seguito come operare per l'installazione:
1) innanzitutto occorre compilare il progetto in versione
release, ricordando di firmare tutti gli assembly con sn.exe altrimenti non
saremmo in grado di registrarlo.
2) ora occorre copiare gli assembly generati nella
posizione in cui desideriamo tenerli. In seguito accederemo a questa directory
mediante il prompt di Visual Studio 2005 e lanceremo il seguente comando:
regasm /codebase
Elite.VisualStudio.CustomTools.dll
In questo modo avremo registrato i componenti dichiarati
nell'assembly in questione che per inciso sono due; Uno per CSharp e uno per
vb.net
3) a questo punto occorre aprire regedit e raggiungere questo
nodo:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\Generators\{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}
4) All'interno di questo nodo occorrerà inserire una chiave il
cui nome sarà quello da utilizzare nell'apposita proprietà di un file per
applicarvi il nostro Custom Tool.
5) Concludiamo creando i seguenti due valori:
CLSID (String) in cui specificare i guid dei due componenti
racchiusi tra graffe
{CE1B4057-D10A-4cd6-8E13-29B4699ACEAD} per
XmlSerializationCSharpGenerator
{7CDAAE56-B3A5-4514-9B0E-8BC1E80B1C68} per
XmlSerializationVBGenerator
GeneratesDesignTimeSource (DWORD) contenete il valore "1".
A questo punto, senza nemmeno dover chiudere Visual Studio se
nel frattempo lo avete lasciato aperto, specificando una delle due stringhe
otterrete immediatamente il file cs o vb contenente il codice generato. Per
ulteriore chiarimento dovete sapere che la generazione del codice avviene
utilizzando lo stesso meccanismo di cui fa uso xsd.exe, con i limiti conosciuti
cui bisogna stare attenti. A tali classi vengono aggiunti alcuni metodi statici
per facilitare la deserializazione.
Giusto per darvi un'idea delle possibilità che questo strumento
mette a disposizione sappiate che nell'esempio allegato ho semplicemente
scaricato con ie il feed rss del mio weblog. Poi ho aggiunto questo file ad un
progetto e impostato il custom tool mi sono ritrovato tutte le classi necessarie
per deserializzarlo e visualizzarli in una piccola applicazione windowsform.
Download: Elite.VisualStudio.CustomTools.zip (301 KB)
powered by IMHO 1.3