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


Commenti (1) -

# | Di .NET e di altre amenita' | 28.03.2006 - 00.15

Aggiungi Commento