Continuo la serie di post che ha riscosso un inatteso successo tornando a parlare di Monad e dei suoi provider. Come promesso la precedente puntata ecco finalmente un po' di codice che spiega come implementare un provider che risponda ad un device fittizio che chiameremo sql:\ ottenendo il risultato di consentirci di navigare lo schema del database come se fosse un filesystem.

Per chiarire l'obbiettivo che ci poniamo innanzitutto proviamo a spiegare in che modo avverrà la navigazione all'interno di SqlServer. Se pensiamo ad un database server Sql, possiamo individuare una sorta di gerarchia riconducibile ad un path analogo a quello del filesystem. Al primo livello avremo il server, poi il database, poi ancora le tabelle ed infine i campi che compongono una singola tabella. La scelta in effetti è arbitraria in quanto è evidente che si sarebbe potuto scegliere un diverso modo di ordinare gli oggetti, ma allo scopo del post, quanto appena descritto è più che sufficiente.

Quindi scrivendo il seguente path dovremmo poter raggiungere i campi della tabella Employees nel database Northwind del server locale:

sql:\(local)\Northwind\Employees

Per ottenere questo risultato il primo passo da compiere è quello di creare una classe, che chiameremo SqlCmdletProvider che eredita da NavigationCmdletProvider. Questa classe dovrà inoltre essere decorata dall'attributo CmdletProviderAttibute oltre naturalmente a implementare l'unico metodo astratto di tale classe. Ecco un breve spezzone di codice:

using System;
using System.Management.Automation;
using System.Management.Automation.Provider;

[CmdletProvider("SqlCmdletProvider", ProviderCapabilities.None)]
public class SqlCmdletProvider : NavigationCmdletProvider
{
    
protected override bool IsValidPath(string path)
    {
        
return true;
    }
}

Dovremo naturalmente ricordarci di importare i namespace di Monad, e di referenziare i relativi assembly che troveremo nella directory di installazione. Ora il nostro provider compila, ma anche ammettendo di installarlo scopriremo che non è in grado di compiere alcuna azione. In particolare manca la possibilità di "agganciarsi" al drive fittizio sql: come richiesto dai requisiti che abbiamo espresso poco fa. E' qui che entrano in gioco la serie di metodi virtuali, esposti dalla classe NavigationCmdletProvider, facendo l'override dei quali si potranno iniziare ad ottenere i comportamenti richiesti. Per poter assegnare il drive sql: al nostro provider dovremo sovrascrivere il metodo InitializeDefaultDrives() il quale dovrà tornare una collection dei drive cui il nostro provider fa capo; Eccone l'implementazione:

protected override Collection<System.Management.Automation.DriveInfo> InitializeDefaultDrives()
{
    Collection<System.Management.Automation.DriveInfo> drives = 
               new Collection<System.Management.Automation.DriveInfo();

    drives.Add(
        
new System.Management.Automation.DriveInfo(
            "sql",
            
this.ProviderInfo,
            "\\", 
            "Sql MSH Navigation Provider", 
            
null));

    
return (drives);
}

Come già detto questo metodo informerà il runtme di quali drive fanno capo al nostro provider. Una volta installato il provider potremmo assicurarci che esso risponda correttamente lanciando la cmdlet get-provider per ottenere quelo che segue:

MSH C:\> get-provider

Name                 Capabilities                                      Drives
----                 ------------                                      ------
SqlCmdletProvider    None                                              {sql}
Alias                ShouldProcess                                     {Alias}
Environment          ShouldProcess                                     {Env}
FileSystem           Filter, ShouldProcess                             {C, D, E, F, G}
Function             ShouldProcess                                     {Function}
Registry             ShouldProcess                                     {HKLM, HKCU}
Variable             ShouldProcess                                     {Variable}
Certificate          ShouldProcess                                     {cert}

Tra i provider installati è elencato anche il nostro e se proviamo a scrivere "cd sql:\" il nostro provider accetterà il percorso specificato così come qualunque altro dato che nel metodo IsValiPath() abbiamo ritornato semplicemente true.

Ora, prima di chiudere il post e lasciarvi per la prossima puntata, è opportuno che spieghi come si fa ad installare il provider in Monad. In effetti questa è la parte se volete più oscura alla qualeho trovato una sola soluzione, ma sospetto che ve ne siano altre che mi sono bellamente sfuggite. Quello che ho fatto io è stato di compilare una nuova shell includendo l'assembly del mio provider ottenendo così un nuovo eseguibile compatto che supporta anche il mio provider; Ecco la linea di comando MSH che ho utilizzato per lo scopo:

make-shell -out sqlshell.exe -namespace MonadProvider -reference MonadProvider.dll

Questo comando, che fa parte el set di Monad in sostanza prende la shell msh.exe, e vi allega il provider referenziato (che comunque dovrà sempre essere presente sotto forma di assembly). Essa poi restituisce un nuovo exe (sqlshell.exe) che può essere distribuito assieme al proprio provider ma che ne racchiude le funzionalità esposte. Mi sembra una bella feature, se pensiamo ad esempio a tool appositamente creati per la manutenzione di particolari ambienti, però mi sarei aspettato anche la possibilità di installare, magari in un file di configurazione il provider senza dover passare per una compilazione. Sono fermamente convinto che questa possibilità ci sia, e di essermi fermato troppo presto nella ricerca. Appena ne so qualcosa evidentemente sarete i primi a saperlo.

powered by IMHO 1.3


per leggere il post originale o inviare un commento visita il seguente indirizzo: Scrivere un provider per Monad (MSH) #2: Inizializzare i drive