Condividi tramite


Archivio di metadati

Aggiornamento: novembre 2007

Il framework di Progettazione Windows Presentation Foundation (WPF) per Visual Studio separa i metadati Design-Time dall'implementazione. La separazione dei metadati dal codice runtime è un importante principio della progettazione per le ragioni seguenti.

  • Le modifiche di compilazione e la logistica di integrazione tra team possono rendere scomoda la compilazione di metadati nel codice del framework.

  • La compilazione di metadati nel codice runtime impedisce agli strumenti esterni, ad esempio WPF Designer o Expression Blend, di modificare quei metadati in un secondo momento. Si tratta di un'importante questione di agilità. Se non vi è separazione tra metadati Design-Time e codice, in Visual Studio non è possibile assegnare una versione alle finestre di progettazione senza richiedere una nuova versione di .NET Framework.

  • La compilazione dei metadati nel runtime aumenta in modo significativo la dimensione dell'assembly del runtime. Gli attributi Design-Time rallentano inoltre il runtime. Le funzionalità di runtime, ad esempio l'associazione dati, che utilizza la riflessione, sono interessate in quanto gli attributi aggiuntivi vengono caricati in memoria.

  • I metadati Design-Time forniscono la "personalità" della finestra di progettazione. Le funzionalità di una finestra di progettazione sono ampiamente legate all'applicazione che la ospita, non al runtime. WPF Designere Expression Blend utilizzano differenti insiemi di metadati per fornire un insieme di funzionalità indirizzato a un tipo specifico di utente.

Archivio di metadati

L'archivio di metadati è un percorso di archiviazione per i metadati Design-Time. L'API per l'archivio di metadati è semplice. Aggiungere una tabella di attributi di metadati chiamando il metodo AddAttributeTable. Quando una tabella viene aggiunta all'archivio di metadati, gli attributi definiti in quella tabella diventano disponibili tramite query TypeDescriptor. Se su un tipo è già stata eseguita una query e la tabella contiene attributi aggiuntivi per questo tipo, viene generato un evento Refreshed per indicare che i metadati del tipo sono stati modificati.

Tabella di attributi

Una tabella di attributi è essenzialmente un dizionario in sola lettura, ma le chiavi e i valori vengono calcolati separatamente. È utile eseguire query su una tabella di attributi per attributi di un particolare tipo. L'insieme effettivo di attributi viene creato su richiesta. Chiamare il metodo GetCustomAttributes per recuperare i metadati personalizzati per un particolare tipo.

Una tabella di attributi supporta solo le proprietà di un tipo. Una tabella di attributi non supporta attributi su campi o metodi.

Generatore di tabelle di attributi

Per creare una tabella di attributi, iniziare creando un'istanza della classe AttributeTableBuilder. Aggiungere metadati al generatore di tabelle di attributi chiamando gli overload AddCustomAttributes. Dopo aver aggiunto i metadati, produrre una tabella di attributi dal generatore di tabelle di attributi chiamando il metodo CreateTable. Poiché i metodi del generatore di tabelle di attributi supportano i delegati di callback, la creazione della tabella di attributi può essere posticipata finché non è necessaria.

Creazione di attributi personalizzati

L'archivio di metadati si basa sul fatto che gli attributi personalizzati dispongono di un override correttamente definito per la proprietà TypeId. L'archivio di metadati utilizza la proprietà TypeId per determinare se due attributi dello stesso tipo o di tipo differente devono essere trattati come le stesse istanze.

La classe base Attribute definisce la proprietà TypeId nel modo seguente.

    public class Attribute
    {
        ...

        public virtual object TypeId
        {
            get
            {
                return base.GetType();
            }
        }

        ...
    }

Questa implementazione fa sembrare due istanze dello stesso Attribute come lo stesso attributo. Una delle istanze sarà ignorata dall'implementazione di TypeDescriptor predefinita. Se questo non è il comportamento desiderato di un attributo personalizzato, come nel caso della classe FeatureAttribute, l'attributo personalizzato deve eseguire l'override della proprietà TypeId per restituire un oggetto univoco per ogni istanza del tipo. Ad esempio, la classe FeatureAttribute esegue l'override della proprietà TypeId utilizzando il codice seguente.

public override object TypeId
{
    get { return this; }
}

Poiché this rappresenta un oggetto univoco per ogni istanza dell'oggetto, FeatureAttribute può decorare in modo sicuro la stessa classe più volte e produrre il risultato desiderato quando utilizzata con l'archivio di metadati.

Convenzione di denominazione per gli assembly di metadati

Il codice Design-Time viene distribuito in speciali assembly di metadati. Le funzionalità di progettazione supportate da tutte le finestre di progettazione sono distribuite in un assembly con ".Design" aggiunto al nome della libreria principale. Le funzionalità in fase di progettazione che sono supportate da Visual Studio sono distribuite solo in un assembly con ".VisualStudio.Design" aggiunto al nome della libreria principale. Nella tabella seguente vengono mostrati nomi di esempio per una libreria di controlli runtime denominata CustomControlLibrary.dll.

Finestra di progettazione

Nome di assembly Design-Time

Solo Visual Studio

CustomControlLibrary.VisualStudio.Design.dll

Solo Expression Blend

CustomControlLibrary.Expression.Design.dll

Tutte le finestre di progettazione

CustomControlLibrary.Design.dll

Caricamento di assembly di metadati

Quando nella finestra di progettazione viene caricato un assembly del runtime, vengono cercati anche i corrispondenti assembly di metadati. Se trovati, questi assembly di metadati vengono caricati immediatamente dopo il caricamento dell'assembly del runtime.

Quando si aggiunge un nuovo riferimento di assembly al progetto, vengono cercati tutti gli assembly di metadati corrispondenti e, se trovati, vengono caricati.

Gli assembly di metadati vengono ricaricati quando vengono ricompilati.

Nota:

Gli assembly di metadati *.Design.dll vengono caricati prima degli assembly *.VisualStudio.Design.dll e *.Expression.Design.dll specifici della finestra di progettazione. I metadati specifici della finestra di progettazione eseguono l'override dei metadati condivisi.

Ordine di ricerca degli assembly di metadati

Il seguente ordine di ricerca si applica agli assembly ai quali viene fatto diretto riferimento dal progetto.

  1. La finestra di progettazione esegue la ricerca nella stessa cartella dell'assembly del runtime a cui si fa riferimento. Questo percorso viene trovato utilizzando lo stesso algoritmo che la compilazione utilizza per trovare l'assembly, che include la ricerca delle cartelle SDK e dei percorsi aggiuntivi.

  2. La finestra di progettazione cerca una sottocartella "Design" nella cartella in cui è presente l'assembly del runtime del controllo.

Sebbene l'assembly del runtime di un controllo possa essere caricato dalla Global Assembly Cache (GAC), il riferimento è sempre puntato a un percorso al di fuori della cache GAC. Spesso questo percorso è nella cartella SDK. WPF Designer utilizza le API di Visual Studio per trovare un assembly con riferimento all'interno del file system, anche quando l'HintPath del progetto non è specificato. La finestra di progettazione tenta di caricare l'assembly di metadati dal percorso che contiene il riferimento all'assembly del runtime del controllo, non dal percorso in cui l'assembly del runtime del controllo viene caricato.

Gli assembly con riferimenti indiretti vengono caricati perché un assembly a cui viene fatto riferimento dal progetto ne contiene i riferimenti. Ad esempio, se il progetto contiene un riferimento all'assembly MyAssembly e MyAssembly contiene un riferimento a MyOtherAssembly (che quindi non è un riferimento diretto del progetto) si considera che MyOtherAssembly sia un riferimento indiretto.

In questo caso, l'assembly non è richiesto per la compilazione e il sistema di compilazione non trova il percorso dell'assembly di riferimento indiretto nel file system. Nella tabella seguente viene mostrato come la finestra di progettazione carica gli assembly ai quali è fatto riferimento indirettamente.

Assembly con riferimenti

Procedura di ricerca

File caricato dalla cache GAC

Nelle cartelle SDK viene eseguita la ricerca del corrispondente assembly di metadati. Se questo assembly viene trovato, il percorso e la sottocartella "Design" relativi vengono utilizzati per cercare gli assembly di metadati corrispondenti.

File caricato da un percorso esterno alla cache GAC

Nel percorso dell'assembly del runtime e nella relativa sottocartella "Design" vengono cercati i corrispondenti assembly di metadati.

Ricerca di un'implementazione di IRegisterMetadata

Gli assembly di metadati devono contenere una o più implementazioni dell'interfaccia IRegisterMetadata. L'implementazione di IRegisterMetadata viene trovata utilizzando la riflessione. Se in un assembly esistono più implementazioni di IRegisterMetadata, per ognuna viene creata un'istanza e viene chiamata nell'ordine restituito dall'API della riflessione.

Vedere anche

Riferimenti

Microsoft.Windows.Design.Metadata

MetadataStore

AttributeTable

AttributeTableBuilder

FeatureAttribute

Altre risorse

Estensibilità di Progettazione WPF