Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Mise à jour : novembre 2007
L'infrastructure du Concepteur Windows Presentation Foundation (WPF) pour Visual Studio découple de l'implémentation les métadonnées au moment du design. La séparation des métadonnées du code du runtime est un principe de conception important pour les raisons suivantes.
La génération de la logistique d'aller et retour et d'intégration entre les équipes peut rendre la compilation des métadonnées dans du code d'infrastructure fastidieuse.
La compilation de métadonnées dans le code du runtime empêche des outils externes, comme le Concepteur WPF et Expression Blend, de modifier ultérieurement ces métadonnées. Il s'agit d'un élément essentiel pour assurer la souplesse. Si les métadonnées au moment du design ne sont pas découplées du code, Visual Studio ne peut pas contrôler la version de ses concepteurs sans requérir une nouvelle version du .NET Framework.
La compilation des métadonnées dans le runtime augmente considérablement la taille de l'assembly de runtime. Les attributs au moment du design ralentissent également le runtime. Les fonctionnalités de runtime, comme la liaison de données, qui utilise la réflexion, sont affectées lorsque des attributs supplémentaires sont chargés en mémoire.
Les métadonnées au moment du design fournissent la "personnalité" du concepteur. Les fonctionnalités d'un concepteur sont en grande partie liées à l'application qui l'héberge, pas au runtime. Le Concepteur WPF et Expression Blend utilisent des jeux de métadonnées différents pour fournir un jeu de fonctionnalités ciblant un type d'utilisateur spécifique.
Magasin de métadonnées
Le magasin de métadonnées est un emplacement de stockage des métadonnées au moment du design. L'API du magasin de métadonnées est simple. Vous ajoutez une table d'attributs de métadonnées en appelant la méthode AddAttributeTable. Lorsqu'une table est ajoutée au magasin de métadonnées, les attributs définis dans cette table sont disponibles via des requêtes TypeDescriptor. Si un type a déjà été interrogé et que la table contient des attributs supplémentaires pour ce type, un événement Refreshed est déclenché pour signaler que les métadonnées du type ont changé.
Table d'attributs
Une table d'attributs est essentiellement un dictionnaire en lecture seule, mais dont les clés et valeurs sont calculées séparément. Il est en effet efficace de rechercher des attributs d'un type particulier dans une table d'attributs. Le jeu réel d'attributs est créé à la demande. Vous appelez la méthode GetCustomAttributes pour récupérer les métadonnées personnalisées d'un type particulier.
Une table d'attributs ne prend en charge que les propriétés d'un type, pas les attributs de champs ou de méthodes.
Générateur de table d'attributs
Pour créer une table d'attributs, vous commencez par créer une instance de la classe AttributeTableBuilder. Vous ajoutez les métadonnées au générateur de table d'attributs en appelant les surcharges AddCustomAttributes. Après avoir ajouté les métadonnées, vous produisez une table d'attributs à partir du générateur de table d'attributs en appelant la méthode CreateTable. Les méthodes du générateur de table d'attributs prenant en charge les délégués de rappel, la création de la table d'attributs peut être différée autant que cela est nécessaire.
Création d'attributs personnalisés
Le magasin de métadonnées suppose que les attributs personnalisés comportent une substitution correctement définie pour leur propriété TypeId. Le magasin de métadonnées utilise la propriété TypeId pour déterminer si deux attributs du même type ou de type différent doivent être traités comme instances identiques.
La classe Attribute de base définit la propriété TypeId comme suit.
public class Attribute
{
...
public virtual object TypeId
{
get
{
return base.GetType();
}
}
...
}
Dans cette implémentation, deux instances du même type Attribute apparaissent comme attribut identique. L'une des instances est ignorée par l'implémentation TypeDescriptor par défaut. Si ce comportement n'est pas souhaité pour un attribut personnalisé (par exemple, pour la classe FeatureAttribute), l'attribut personnalisé doit substituer la propriété TypeId pour retourner un objet unique pour chaque instance de type. Par exemple, la classe FeatureAttribute substitue la propriété TypeId en utilisant le code suivant.
public override object TypeId
{
get { return this; }
}
Étant donné que this représente un objet unique pour chaque instance d'objet, FeatureAttribute peut décorer plusieurs fois la même classe en toute sécurité et produire le résultat souhaité en cas d'utilisation avec le magasin de métadonnées.
Convention d'affectation de noms pour les assemblys de métadonnées
Le code au moment du design est déployé dans des assemblys de métadonnées spéciaux. Les fonctionnalités au moment du design prises en charge par tous les concepteurs sont déployées dans un assembly dont le nom de la bibliothèque principale comporte le suffixe ".Design". Les fonctionnalités au moment du design prises en charge par Visual Studio uniquement sont déployées dans un assembly dont le nom de la bibliothèque principale comporte le suffixe ".VisualStudio.Design". Le tableau suivant affiche des exemples de noms pour une bibliothèque de contrôles runtime nommée CustomControlLibrary.dll.
Concepteur |
Nom de l'assembly au moment du design |
|---|---|
Visual Studio uniquement |
CustomControlLibrary.VisualStudio.Design.dll |
Expression Blend uniquement |
CustomControlLibrary.Expression.Design.dll |
Tous les concepteurs |
CustomControlLibrary.Design.dll |
Chargement d'assemblys de métadonnées
Lorsque le concepteur charge un assembly de runtime, le concepteur recherche également des assemblys de métadonnées correspondants. S'ils sont trouvés, les assemblys de métadonnées correspondants sont chargés directement après le chargement de l'assembly de runtime.
Lorsque vous ajoutez une nouvelle référence d'assembly à votre projet, tous les assemblys de métadonnées correspondants sont recherchés et chargés, s'il en existe.
Les assemblys de métadonnées sont rechargés lorsqu'ils sont régénérés.
Remarque : |
|---|
Les assemblys de métadonnées *.Design.dll sont chargés avant les assemblys *.VisualStudio.Design.dll et *.Expression.Design.dll spécifiques du concepteur. Les métadonnées spécifiques du concepteur substituent les métadonnées partagées. |
Ordre de recherche d'assemblys de métadonnées
L'ordre de recherche suivant s'applique aux assemblys référencés directement par le projet.
Le concepteur effectue une recherche dans le même dossier que l'assembly de runtime référencé. Cet emplacement est retrouvé à l'aide du même algorithme que celui utilisé par la génération pour rechercher l'assembly, qui inclut la recherche des dossiers SDK et de chemins d'accès supplémentaires.
Le concepteur recherche un sous-dossier "Design" dans le dossier où l'assembly de runtime du contrôle est situé.
Il est possible de charger l'assembly de runtime d'un contrôle à partir du Global Assembly Cache (GAC). Toutefois, la référence pointe toujours vers un emplacement en dehors du GAC. Cet emplacement est souvent situé dans le dossier SDK. Le Concepteur WPF utilise des API Visual Studio pour rechercher un assembly référencé dans le système de fichiers, même si le HintPath du projet n'est pas spécifié. Le concepteur tente de charger l'assembly de métadonnées à partir de l'emplacement où l'assembly de runtime du contrôle est référencé, pas à partir de l'endroit où cet assembly est chargé.
Les assemblys référencés indirectement sont chargés, car ils sont référencés à partir d'un assembly référencé par le projet. Par exemple, supposons que vous disposez d'un projet qui contient une référence à l'assembly MyAssembly et que MyAssembly contient une référence à MyOtherAssembly, qui n'est pas référencé directement par le projet. Dans ce cas, MyOtherAssembly est considéré comme étant référencé indirectement.
Dans ce cas, l'assembly n'est pas requis pour la génération et le système de génération ne trouve pas l'emplacement de l'assembly référencé indirectement dans le système de fichiers. Le tableau suivant indique comment le concepteur charge les assemblys référencés indirectement.
Assembly référencé |
Procédure de recherche |
|---|---|
Fichier chargé du GAC |
L'assembly de métadonnées correspondant est recherché dans les dossiers SDK. Si cet assembly est trouvé, son chemin d'accès et son sous-dossier "Design" sont utilisés pour rechercher tous les assemblys de métadonnées correspondants. |
Fichier chargé d'un emplacement en dehors du GAC |
Les assemblys de métadonnées correspondants sont recherchés dans le chemin d'accès de l'assembly de runtime et dans son sous-dossier "Design". |
Recherche d'une implémentation IRegisterMetadata
Les assemblys de métadonnées doivent contenir une ou plusieurs implémentations de l'interface IRegisterMetadata. L'implémentation IRegisterMetadata est recherchée à l'aide de la réflexion. Si un assembly contient plusieurs implémentations IRegisterMetadata, chacune est instanciée et appelée dans l'ordre retourné par l'API de réflexion.
Voir aussi
Référence
Microsoft.Windows.Design.Metadata
Remarque :