Claudio Brotto

SPContentDatabase e CLS *non* Compliance

Durante la creazione di uno script PowerShell di "dumping" di una site collection, sono incappato in un errore che mi ha incuriosito.

Nel tentativo di accedere alla property ContentDatabase di un'istanza di SPSite, la shell mi ha risposto picche con il seguente errore:

PS D:\Users\clu> $site.ContentDatabase
out-lineoutput : The field/property: "Id" for type: "Microsoft.SharePoint.Administration.SPContentDatabase" differs only in case from the field/property: "ID". Failed to use non CLS compliant type.
PS D:\Users\clu>

Mmhhh ... senti senti ... vuoi mica dire ...

Per garantire l'operabilità tra linguaggi che targetizzano il .NET Framework, è stato definito un insieme di regole, che vanno sotto il nome di Common Language Specifications.

Rispettando tali regole (non è difficile ... i compilatori ci danno una mano in questi casi) gli autori di librerie possono essere certi che i tipi che definiscono saranno utilizzabili senza problemi da *qualsiasi* linguaggio usi il client.

Per fare un esempio, C# supporta i tipi pointer, che però non sono CLS-Compliant. Inutile esporli pubblicamente se, poi, è richiesta l'interoperabilità :-)

C'è un'altra regola, forse la più nota di tutte, che impone di assegnare nomi differenti ai membri (overload a parte), senza considerare maiuscole e minuscole.

Le verifiche, chiaramente, si applicano solamente all'interfaccia che il tipo espone al chiamante (quindi ai membri public e protected).

In C#, ad esempio, è molto frequente uno stile di codifica che utilizza camelCasing per i campi privati e PascalCasing per le proprietà pubbliche che li incapsulano, e il tutto è perfettamente lecito.

Per curiosità ecco la definizione di SPContentDatabase (snapshots courtesy of Reflector).

SPContentDatabase ha la seguente catena di ereditarietà:

 

Definisce un campo pubblico ID, di tipo System.Guid:

 

Ma SPPersistedObject (tre livelli di ereditarietà sopra) definisce a sua volta un membro pubblico, Id, di tipo System.Guid:

Andando a spulciare il body del getter di SPContentDatabase::Id (minuscolo) ... indovinate un po' che valore ritorna ? (Vedere penultima immagine).

In realtà il caso è ancora più interessante perchè, nella documentazione di SPContentDatabase::ID, il membro è indicato come obsolete. Era presente nell'OM di WSS2.0, ora consigliano di usare la property Id (minuscolo) della classe base.

Dicevo interessante perchè è un esempio delle scelte che si trova ad affrontare chi rilascia la v2 dei propri componenti (a maggior ragione quando gli utilizzatori sono piuttosto numerosi :-)).

Eliminare la proprietà, a questo punto ridondante, da SPContentDatabase sarebbe stata la soluzione più pulita e avrebbe garantito la CLS compliance.

Ma avrebbe di fatto "rotto" la retrocompatibilità.

Ho fatto un giro per leggere quali sono i commenti a riguardo. Qui ad esempio, con annessa indicazione di un modo per circumnavigare il problema. Viene proposto di utilizzare GetMethod per invocare il getter (il metodo get_ID) di SPContentDatabase::ID.

E' chiaro che andando di reflection molte questioni si riescono a risolvere (e se è per quello, ad avere i diritti, si riescono tranquillamente ad invocare metodi privati o a cambiare lo stato interno degli oggetti).

Però ... è proprio una cura del sintomo :-(

Posted: giu 08 2008, 08.18 by devlizard | with no comments
Filed under: ,