Partilhar via


Armazenamento de metadados

A estrutura Windows Presentation Foundation (WPF) Designer for Visual Studio torna metadados de tempo de design dissociados de implementação.Separar código de tempo de execução e metadados é um importante princípio de projeto pelos seguintes motivos.

  • Criar logísticas de ambientação e de integração entre equipes pode tornar complicada a compilação de metadados em código de Framework.

  • Compilar metadados no código de tempo de execução impede ferramentas externas, como o WPF Designer ou Expression Blend, de modificarem esses metadados posteriormente.Este é um problema de chave para agilidade. Sem separação de metadados de time de design do código, Visual Studio não é possível versão seus designers sem exigir uma nova versão do .NET Framework.

  • Compilar metadados em tempo de execução aumenta significativamente o tamanho da montagem em tempo de execução.Os atributos de tempo de design também diminuem o tempo de execução.Recursos de tempo de execução, tais como as associação de dados, que utiliza o reflexo, são afetados à medida que atributos adicionais são carregados na memória.

  • Metadados de tempo de design fornecem a “ personalidade ” do designer.Os recursos de um designer amplamente estão ligados ao aplicativo que hospeda-lo, não o tempo de execução.WPF Designer e expressão Blend usar conjuntos diferentes de metadados para oferecer um conjunto de recursos direcionada a um tipo específico de usuário.

O armazenamento de metadados

O armazenamento de metadados é um local de armazenamento para os metadados de tempo de design.A API para o armazenamento de metadados é simples.Você adiciona uma tabela de atributos de metadados chamando o método AddAttributeTable.Quando uma tabela é adicionada ao armazenamento, os atributos definidos na tabela que ficam disponíveis através de consultas a TypeDescriptor.Se um tipo já tenha sido consultado, e a tabela contém atributos adicionais para esse tipo, um evento Refreshed é gerado para reportar que os metadados do tipo foram alterados.

A tabela de atributo

Um tabela de atributos é essencialmente um dicionário somente-leitura, mas as chaves e valores são computados separadamente.Isso é eficiente para consultar um tabela de atributos por atributos de um tipo específico.O conjunto real de atributos é criado sob demanda.Você chama o método GetCustomAttributes para recuperar os metadados personalizados para um tipo específico.

Um tabela de atributos suporta apenas as propriedades de um tipo.Um tabela de atributos não suporta atributos em campos ou métodos.

O construtor de tabela de atributos

Para criar um tabela de atributos, você inicia com a criação de uma instância da classe AttributeTableBuilder.Você adiciona metadados ao construtor de tabela de atributos chamando as sobrecargas AddCustomAttributes.Quando você terminar de adicionar os metadados, você produz um tabela de atributos a partir de construtor de tabela de atributos chamando o método CreateTable.Os métodos do construtor de tabela de atributos dão suporte a representantes de retorno de chamada, portanto, a criação da tabela de atributos pode ser adiada até que seja necessária.

Criação de atributo personalizado

O armazenamento de metadados depende do fato de que atributos personalizados tenham uma substituição definida corretamente para sua propriedade TypeId.O armazenamento de metadados usa a propriedade TypeId para determinar se dois atributos do mesmo ou de outro tipo devem ser tratados como sendo as mesmas instâncias.

A classe base Attribute define a propriedade TypeId da seguinte maneira.

    public class Attribute
    {
        ...

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

        ...
    }

Essa implementação faz duas instâncias do mesmo tipo Attribute aparecerem como sendo o mesmo atributo.Uma das instâncias será ignorada pela implementação padrão de TypeDescriptor.Se este for não o comportamento desejado de um atributo personalizado, como é o caso com a classe FeatureAttribute,o atributo personalizado deve substituir a propriedade TypeId para retornar um objeto exclusivo para cada instância de tipo.Por exemplo, a classe FeatureAttribute substitui a propriedade TypeId usando o código a seguir.

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

Como this representa um objeto exclusivo para cada instância do objeto, FeatureAttribute pode decorar com segurança a mesma classe várias vezes e produzir o resultado desejado quando ele é usado em conjunto com o armazenamento de metadados.

Cconvenção de nomeação para conjuntos de metadados

Código em tempo de design é implantado em conjuntos de módulos (assemblies) de metadados especiais.Recursos em tempo de design que têm suporte por todos os designers são implantados em um conjunto de módulos (assembly) com ".Design" acrescentado ao nome da biblioteca principal.Somente recursos em tempo de design que têm suporte do Visual Studio são implantados em um conjunto de módulos (assembly) com ". VisualStudio.Design " acrescentado ao nome da biblioteca principal.A tabela a seguir mostra exemplos de nomes para uma biblioteca de controle de tempo de execução chamada CustomControlLibrary.dll.

Designer

Nome do conjunto de tempo de design

Somente Visual Studio

CustomControlLibrary.VisualStudio.Design.dll

Somente Expression Blend

CustomControlLibrary.Expression.Design.dll

Todos os designers

CustomControlLibrary.Design.dll

Carregando conjuntos de módulos (assemblies) de metadados

Quando o designer carrega um conjunto de tempo de execução, o designer também procura por conjuntos de módulos (assemblies) de metadados correspondentes.Se os conjuntos de metadados correspondentes são encontrados, eles são carregados imediatamente após o conjunto de tempo de execução ser carregado.

Quando você adiciona uma nova referência de conjunto de módulos (assembly) ao seu projeto, é procurada em todos os conjuntos de módulos (assemblies) de metadados correspondentes e carregada se encontrada.

Os conjuntos de módulos (assemblies) de metadados são recarregados quando eles são recriados.

Observação:

Conjuntos de módulos (assemblies) de metadados *. Design.dll são carregados antes dos conjuntos de módulos (assemblies) de designer específicos *. VisualStudio.Design.dll e *. Expression.Design.dll x.Metadados de designer específico substitui metadados compartilhados.

Ordem de pesquisa de conjunto de módulos (Assembly) de metadados

A ordem de pesquisa a seguir se aplica aos conjuntos de módulos (assemblies) mencionados diretamente pelo projeto.

  1. O designer procura na mesma pasta que o assembly de tempo de execução referenciado.Esse local é encontrado usando o mesmo algoritmo que a compilação usa para localizar o módulo (assembly), o que inclui pesquisar as pastas SDK e caminhos adicionais.

  2. O designer procura uma subpasta "Design" na pasta onde está o conjunto de módulos (assembly) de tempo de execução do controle.

Embora um conjunto de módulos (assembly) de tempo de execução do controle pode ser carregado fora do cache global de assemblies (GAC), a referência é sempre a um local fora de GAC.Geralmente esse local está na pasta SDK.O WPF Designer usa APIs do Visual Studio para localizar um conjunto de módulos (assembly) referenciado no sistema de arquivos, mesmo quando o projeto HintPath não é especificado.O designer tenta carregar o conjunto de módulos (assembly) de metadados do local onde o conjunto de módulos (assembly) de tempo de execução do controle é referenciado, não de onde o conjunto de módulos (assembly) do tempo de execução é carregado.

Conjuntos de módulos (assemblies) referenciados indiretamente são carregados porque eles são referenciados de um conjunto de módulos (assembly) referenciado pelo projeto.Por exemplo, se você tiver um projeto com uma referência ao assembly MyAssembly e MyAssembly tem uma referência a MyOtherAssembly, que não é referenciado diretamente, o projeto, MyOtherAssembly é considerado para ser referenciado indiretamente.

Nesse caso, o assembly não é necessário para a compilação, e o sistema de compilação não encontra o local do conjunto de módulos (assembly) referenciado indiretamente no sistema de arquivos.A tabela a seguir mostra como o designer carrega conjuntos de módulos (assemblies) referenciados indiretamente.

Assembly referenciado

Procedimento de pesquisa

Arquivo carregado a partir de GAC

Pesquisa-se nas pastas SDK pelo conjunto de módulos (assembly) de metadados correspondente.Se este conjunto de módulos (assembly) é encontrado, seu caminho e sua subpasta “ Design ” são usados para pesquisar por conjuntos de módulos (assemblies) de metadados correspondentes.

Arquivo carregado a partir de um local fora de GAC

Pesquisa-se o caminho do conjunto de módulos (assembly) de tempo de execução e sua subpasta “ Design ” pelos conjuntos de módulos (assemblies) de metadados correspondentes.

Localizando uma implementação IRegisterMetadata

Os conjuntos de módulos (assemblies) de metadados devem conter uma ou mais implementações da interface IRegisterMetadata.A implementação de IRegisterMetadata é encontrada por meio de reflexão.Se existirem várias implementações IRegisterMetadata em um conjunto de módulos (assembly), cada uma é instanciada e chamada na ordem retornada pela API de reflexão.

Consulte também

Referência

Microsoft.Windows.Design.Metadata

MetadataStore

AttributeTable

AttributeTableBuilder

FeatureAttribute

Outros recursos

Extensibilidade do WPF Designer