Passo a passo: Inserir tipos de assemblies gerenciados no Visual Studio

Se você inserir informações de um assembly gerenciado de nome forte, você poderá acoplar vagamente tipos em um aplicativo para atingir a independência de versão. Isto é, seu programa pode ser escrito para usar tipos de qualquer versão de uma biblioteca gerenciada sem precisar ser recompilado para cada versão nova.

A incorporação de tipo é frequentemente usada com a interoperabilidade COM, como um aplicativo que usa objetos de automação do Microsoft Office. Inserir informações de tipo permite que o mesmo build de um programa funcione com diferentes versões do Microsoft Office em diferentes computadores. No entanto, você também pode usar a inserção de tipo com uma solução totalmente gerenciada.

Depois de especificar as interfaces públicas que podem ser inseridas, crie classes de runtime que implementam essas interfaces. Um programa cliente pode inserir as informações de tipo para essas interfaces em tempo de design referenciando o assembly que contém as interfaces públicas e configurando a propriedade Embed Interop Types da referência como True. O programa cliente pode, então, carregar instâncias dos objetos de runtime de tipo como essas interfaces. Isso é equivalente a usar o compilador de linha de comando e fazer referência ao assembly usando a opção do compilador EmbedInteropTypes.

Se você criar uma nova versão do seu assembly de runtime de nome forte, o programa cliente não precisará ser recompilado. O programa cliente continua a usar qualquer versão do assembly em runtime que está disponível para ele, usando as informações de tipo inseridas para as interfaces públicas.

Neste passo a passo, você vai:

  1. Criar um assembly de nome forte com uma interface pública que contém informações de tipo que podem ser inseridas.
  2. Criar um assembly de runtime de nome forte que implementa a interface pública.
  3. Criará um programa cliente que insere as informações de tipo da interface pública e criará uma instância da classe do assembly de runtime.
  4. Modificará e recompilará o assembly de runtime.
  5. Executar o programa cliente para garantir o uso da nova versão do assembly de runtime sem a necessidade de recompilá-lo.

Observação

Seu computador pode mostrar diferentes nomes ou locais para alguns dos elementos de interface do usuário do Visual Studio nas instruções a seguir. A edição do Visual Studio que você possui e as configurações que você usa determinam esses elementos. Para obter mais informações, consulte Personalizando o IDE.

Condições e limitações

Você pode inserir informações de tipo de um assembly nas seguintes condições:

  • O assembly expõe pelo menos uma interface pública.
  • As interfaces inseridas são anotadas com atributos ComImport e atributos Guid com GUIDs exclusivos.
  • O assembly é anotado com o atributo ImportedFromTypeLib ou o atributo PrimaryInteropAssembly e um atributo Guid de nível do assembly. Os modelos de projeto do Visual C# e do Visual Basic incluem por padrão um atributo Guid no nível do assembly.

Como a principal função da inserção de tipo é dar suporte a assemblies de interoperabilidade COM, as limitações a seguir se aplicam ao inserir informações de tipo em uma solução totalmente gerenciada:

  • Somente os atributos específicos à interoperabilidade COM são inseridos. Os outros atributos são ignorados.
  • Se um tipo usar parâmetros genéricos e o tipo de parâmetro genérico for um tipo inserido, esse tipo não poderá ser usado em um limite de assembly. Os exemplos de cruzar um limite de assembly incluem chamar um método de outro assembly ou derivar um tipo de um tipo definido em outro assembly.
  • Constantes não são inseridas.
  • A classe System.Collections.Generic.Dictionary<TKey,TValue> não dá suporte a um tipo inserido como uma chave. Você pode implementar seu próprio tipo de dicionário para dar suporte a um tipo inserido como uma chave.

Criar uma interface

A primeira etapa é criar o assembly de interface de equivalência do tipo.

  1. No Visual Studio, selecione Arquivo>Novo>Projeto.

  2. Na caixa de diálogo Criar um novo projeto, digite a biblioteca de classes na caixa Pesquisar modelos. Selecione o modelo de biblioteca de classes (.NET Framework) C# ou Visual Basic na lista e selecione Avançar.

  3. Na caixa de diálogo Configurar seu novo projeto, em Nome do projeto, digite TypeEquivalenceInterface e selecione Criar. Quando um novo projeto é criado.

  4. Em Gerenciador de Soluções, clique com o botão direito no arquivo Class1.cs ou Class1.vb, selecione Renomear e renomeie o arquivo de Class1 para ISampleInterface. Responda Sim ao prompt para renomear também a classe para ISampleInterface. Essa classe representará a interface pública para a classe.

  5. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceInterface e selecione Propriedades.

  6. Selecione Compilar no painel esquerdo da tela Propriedades e defina o Caminho de saída como um local no computador, por exemplo, C:\TypeEquivalenceSample. Você usará o mesmo local ao longo deste passo a passo.

  7. Selecione Build>Strong nomeando no painel esquerdo da tela Propriedades e, em seguida, marque a caixa de seleção Assinar o assembly. Em Strong name key file, selecione Browse.

  8. Navegue até e selecione o arquivo key.snk que você criou no projeto TypeEquivalenceInterface e selecione OK. Para obter mais informações, confira Criar um par de chaves pública-privada.

  9. Abra o arquivo de classe ISampleInterface no editor de código e substitua o conteúdo pelo seguinte código para criar a interface ISampleInterface:

    using System;
    using System.Runtime.InteropServices;
    
    namespace TypeEquivalenceInterface
    {
        [ComImport]
        [Guid("8DA56996-A151-4136-B474-32784559F6DF")]
        public interface ISampleInterface
        {
            void GetUserInput();
            string UserInput { get; }
        }
    }
    
    Imports System.Runtime.InteropServices
    
    <ComImport()>
    <Guid("8DA56996-A151-4136-B474-32784559F6DF")>
    Public Interface ISampleInterface
        Sub GetUserInput()
        ReadOnly Property UserInput As String
    End Interface
    
  10. No menu Ferramentas, selecione Criar Guide, na caixa de diálogo Criar GUID, selecione o Formato do Registro. Selecione Copiar e, em seguida, selecione Sair.

  11. No atributo Guid do código, substitua o GUID de exemplo pelo GUID copiado e remova as chaves ({ }).

  12. Em Gerenciador de Soluções, expanda a pasta Propriedades e selecione o arquivo AssemblyInfo.cs ou AssemblyInfo.vb. No editor de códigos, adicione o seguinte atributo ao arquivo:

    [assembly: ImportedFromTypeLib("")]
    
    <Assembly: ImportedFromTypeLib("")>
    
  13. Selecione Arquivo>Salvar Tudo ou pressione Ctrl+Shift+S para salvar os arquivos e o projeto.

  14. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceInterface e selecione Compilar. O arquivo .dll da biblioteca de classes é compilado e salvo no caminho de saída de build especificado, por exemplo, C:\TypeEquivalenceSample.

Criar uma classe de runtime

Em seguida, crie a classe de runtime de equivalência de tipo.

  1. No Visual Studio, selecione Arquivo>Novo>Projeto.

  2. Na caixa de diálogo Criar um novo projeto, digite a biblioteca de classes na caixa Pesquisar modelos. Selecione o modelo de biblioteca de classes (.NET Framework) C# ou Visual Basic na lista e selecione Avançar.

  3. Na caixa de diálogo Configurar seu novo projeto, em Nome do projeto, digite TypeEquivalenceRuntime e selecione Criar. Quando um novo projeto é criado.

  4. Em Gerenciador de Soluções, clique com o botão direito no arquivo Class1.cs ou Class1.vb, selecione Renomear e renomeie o arquivo de Class1 para SampleClass. Responda Sim ao prompt para renomear também a classe para SampleClass. Essa classe implementa a interface ISampleInterface.

  5. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceInterface e selecione Propriedades.

  6. Selecione Compilar no painel esquerdo da tela Propriedades e defina o Caminho de saída como o mesmo local usado para o projeto TypeEquivalenceInterface, por exemplo, C:\TypeEquivalenceSample.

  7. Selecione Build>Strong nomeando no painel esquerdo da tela Propriedades e, em seguida, marque a caixa de seleção Assinar o assembly. Em Strong name key file, selecione Browse.

  8. Navegue até e selecione o arquivo key.snk que você criou no projeto TypeEquivalenceInterface e selecione OK. Para obter mais informações, confira Criar um par de chaves pública-privada.

  9. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceRuntime e selecione Adicionar>Referência.

  10. Na caixa de diálogo Gerenciador de Referência, selecione Procurar e navegue até a pasta de caminho de saída. Selecione o arquivo TypeEquivalenceInterface.dll, selecione Adicionar e selecione OK.

  11. Em Gerenciador de Soluções, expanda a pasta Referências e selecione a referência TypeEquivalenceInterface. No painel Propriedades, defina Versão Específica como Falso se ainda não tiver feito isso.

  12. Abra o arquivo de classe SampleClass no editor de código e substitua o conteúdo pelo seguinte código para criar a classe SampleClass:

    using System;
    using TypeEquivalenceInterface;
    
    namespace TypeEquivalenceRuntime
    {
        public class SampleClass : ISampleInterface
        {
            private string p_UserInput;
            public string UserInput { get { return p_UserInput; } }
    
            public void GetUserInput()
            {
                Console.WriteLine("Please enter a value:");
                p_UserInput = Console.ReadLine();
            }
        }
    }
    
    Imports TypeEquivalenceInterface
    
    Public Class SampleClass
        Implements ISampleInterface
    
        Private p_UserInput As String
        Public ReadOnly Property UserInput() As String Implements ISampleInterface.UserInput
            Get
                Return p_UserInput
            End Get
        End Property
    
        Public Sub GetUserInput() Implements ISampleInterface.GetUserInput
            Console.WriteLine("Please enter a value:")
            p_UserInput = Console.ReadLine()
        End Sub
    End Class
    
  13. Selecione Arquivo>Salvar Tudo ou pressione Ctrl+Shift+S para salvar os arquivos e o projeto.

  14. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceRuntime e selecione Compilar. O arquivo DLL da biblioteca de classes é compilado e salvo no caminho de saída de build especificado.

Criar um projeto de cliente

Por fim, crie um programa cliente de equivalência de tipo que faça referência ao assembly de interface.

  1. No Visual Studio, selecione Arquivo>Novo>Projeto.

  2. Na caixa de diálogo Criar um novo projeto, digite console na caixa Pesquisar modelos. Selecione o modelo de Aplicativo de console (.NET Framework) C# ou Visual Basic na lista e selecione Avançar.

  3. Na caixa de diálogo Configurar seu novo projeto, em Nome do projeto, digite TypeEquivalenceClient e selecione Criar. Quando um novo projeto é criado.

  4. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceClient e selecione Propriedades.

  5. Selecione Compilar no painel esquerdo da tela Propriedades e defina o Caminho de saída como o mesmo local usado para o projeto TypeEquivalenceInterface, por exemplo, C:\TypeEquivalenceSample.

  6. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceClient e selecione Adicionar>Referência.

  7. Na caixa de diálogo Gerenciador de Referência, se o arquivo TypeEquivalenceInterface.dll já estiver listado, selecione-o. Caso contrário, selecione Procurar, navegue até a pasta de caminho de saída, selecione o arquivo TypeEquivalenceInterface.dll (não o TypeEquivalenceRuntime.dll) e selecione Adicionar. Selecione OK.

  8. Em Gerenciador de Soluções, expanda a pasta Referências e selecione a referência TypeEquivalenceInterface. No painel Propriedades, defina Inserir Tipos de Interoperação como Verdadeiro.

  9. Abra o arquivo Program.cs ou Module1.vb no editor de código e substitua seu conteúdo pelo seguinte código para criar o programa cliente:

    using System;
    using System.Reflection;
    using TypeEquivalenceInterface;
    
    namespace TypeEquivalenceClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                Assembly sampleAssembly = Assembly.Load("TypeEquivalenceRuntime");
                ISampleInterface sampleClass =
                    (ISampleInterface)sampleAssembly.CreateInstance("TypeEquivalenceRuntime.SampleClass");
                sampleClass.GetUserInput();
                Console.WriteLine(sampleClass.UserInput);
                Console.WriteLine(sampleAssembly.GetName().Version.ToString());
                Console.ReadLine();
            }
        }
    }
    
    Imports System.Reflection
    Imports TypeEquivalenceInterface
    
    Module Module1
    
        Sub Main()
            Dim sampleAssembly = Assembly.Load("TypeEquivalenceRuntime")
            Dim sampleClass As ISampleInterface = CType( _
                sampleAssembly.CreateInstance("TypeEquivalenceRuntime.SampleClass"), ISampleInterface)
            sampleClass.GetUserInput()
            Console.WriteLine(sampleClass.UserInput)
            Console.WriteLine(sampleAssembly.GetName().Version)
            Console.ReadLine()
        End Sub
    
    End Module
    
  10. Selecione Arquivo>Salvar Tudo ou pressione Ctrl+Shift+S para salvar os arquivos e o projeto.

  11. Pressione Ctrl+F5 para compilar e executar o programa. Observe que a saída do console retorna o assembly versão 1.0.0.0.

Modificar a interface

Agora, modifique o assembly da interface e altere sua versão.

  1. No Visual Studio, selecione Arquivo>Abrir>Projeto/Solução e abra o projeto TypeEquivalenceInterface.

  2. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceInterface e selecione Propriedades.

  3. Selecione Aplicativo no painel esquerdo da tela Propriedades e selecione Informações do Assembly.

  4. Na caixa de diálogo Informações do Assembly, altere os valores de Versão do assembly e Versão do arquivo para 2.0.0.0 e selecione OK.

  5. Abra o arquivo SampleInterface.cs ou SampleInterface.vb e adicione a seguinte linha de código à interface ISampleInterface:

    DateTime GetDate();
    
    Function GetDate() As Date
    
  6. Selecione Arquivo>Salvar Tudo ou pressione Ctrl+Shift+S para salvar os arquivos e o projeto.

  7. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceInterface e selecione Compilar. Uma nova versão do arquivo DLL da biblioteca de classes é compilado e salvo no caminho de saída do build.

Modificar a classe de runtime

Modifique também a classe de runtime e atualize sua versão.

  1. No Visual Studio, selecione Arquivo>Abrir>Projeto/Solução e abra o projeto TypeEquivalenceRuntime.

  2. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceRuntime e selecione Propriedades.

  3. Selecione Aplicativo no painel esquerdo da tela Propriedades e selecione Informações do Assembly.

  4. Na caixa de diálogo Informações do Assembly, altere os valores de Versão do assembly e Versão do arquivo para 2.0.0.0 e selecione OK.

  5. Abra o arquivo SampleClass.cs ou SampleClass.vb, e adicione o seguinte código à classe SampleClass:

     public DateTime GetDate()
     {
         return DateTime.Now;
     }
    
    Public Function GetDate() As DateTime Implements ISampleInterface.GetDate
        Return Now
    End Function
    
  6. Selecione Arquivo>Salvar Tudo ou pressione Ctrl+Shift+S para salvar os arquivos e o projeto.

  7. No Gerenciador de Soluções, clique com o botão direito no projeto TypeEquivalenceRuntime e selecione Compilar. Uma nova versão do arquivo DLL da biblioteca de classes é compilado e salvo no caminho de saída do build.

Executar o programa cliente atualizado

Vá para o local da pasta de saída do build e execute TypeEquivalenceClient.exe. Observe que a saída do console agora reflete a nova versão do assembly TypeEquivalenceRuntime, 2.0.0.0, sem que o programa seja recompilado.

Confira também