Tutorial: Incrustar los tipos de los ensamblados administrados (C# y Visual Basic)

Si se incrusta información de tipos de un ensamblado administrado con nombre seguro, los tipos se pueden acoplar de manera imprecisa en una aplicación para conseguir la independencia de la versión. Es decir, el programa se puede escribir para usar los tipos de distintas versiones de una biblioteca administrada sin tener que volver a compilarse para cada versión.

La incrustación de tipos se usa frecuentemente con la interoperabilidad COM, como una aplicación que usa los objetos de automatización de Microsoft Office. La incrustación de información de tipos permite que una misma compilación de un programa funcione con versiones distintas de Microsoft Office en equipos diferentes. Sin embargo, también se puede usar la incrustación de tipos con una solución totalmente administrada.

La información de tipos se puede incrustar desde un ensamblado con las siguientes características:

  • El ensamblado expone al menos una interfaz pública.

  • Las interfaces incrustadas se anotan con un atributo ComImport y un atributo Guid (además de un GUID único).

  • El ensamblado se anota con el atributo ImportedFromTypeLib o PrimaryInteropAssembly y un atributo Guid de nivel de ensamblado. (De forma predeterminada, las plantillas de proyecto de Visual Basic y Visual C# incluyen un atributo Guid de nivel de ensamblado).

Una vez especificadas las interfaces públicas que se pueden incrustar, se pueden crear clases en tiempo de ejecución que implementen dichas interfaces. A continuación, un programa cliente puede incrustar la información de tipos de dichas interfaces en tiempo de diseño. Para ello, debe hacer referencia al ensamblado que contiene las interfaces públicas y establecer la propiedad Embed Interop Types de la referencia en True. Esto equivale a usar el compilador de la línea de comandos y hacer referencia al ensamblado mediante la opción del compilador /link. A continuación, el programa cliente puede cargar instancias de los objetos en tiempo de ejecución escritos como esas interfaces. Si se crea una nueva versión del ensamblado en tiempo de ejecución con nombre seguro, no es necesario volver a compilar el programa cliente con el ensamblado en tiempo de ejecución actualizado. En su lugar, el programa cliente continúa usando cualquier versión disponible del ensamblado en tiempo de ejecución y usa la información de tipos incrustada para las interfaces públicas.

Dado que la función primaria de la incrustación de tipos es permitir la incrustación de información sobre los tipos desde los ensamblados de interoperabilidad COM, al incrustar información de tipos en una solución completamente administrada se aplican las limitaciones siguientes:

  • Solo se incrustan atributos específicos de la interoperabilidad COM; otros atributos se omiten.

  • Si un tipo usa parámetros genéricos y el tipo de parámetro genérico es un tipo incrustado, ese tipo no se puede usar a través de los límites del ensamblado. Entre los ejemplos en los que se cruza un límite de ensamblado se encuentran las llamadas a un método desde otro ensamblado o la derivación de un tipo a partir de otro definido en un ensamblado distinto.

  • Las constantes no se incrustan.

  • La clase System.Collections.Generic.Dictionary<TKey, TValue> no admite un tipo incrustado como clave. Puede implementar su propio tipo de diccionario para admitir un tipo incrustado como clave.

En este tutorial, hará lo siguiente:

  • Crear un ensamblado con nombre seguro con una interfaz pública que contiene información de tipos que se puede incrustar.

  • Crear un ensamblado en tiempo de ejecución con nombre seguro que implementa esa interfaz pública.

  • Crear un programa cliente que incrusta la información de tipos de la interfaz pública y crea una instancia de la clase a partir del ensamblado en tiempo de ejecución.

  • Modificar y recompilar el ensamblado en tiempo de ejecución.

  • Ejecutar el programa cliente para comprobar que se usa la nueva versión del ensamblado en tiempo de ejecución sin tener que volver a compilar el programa cliente.

Nota

Es posible que su equipo muestre nombres o ubicaciones diferentes para algunos de los elementos de la interfaz de usuario de Visual Studio incluidos en las instrucciones siguientes. La edición de Visual Studio que se tenga y la configuración que se utilice determinan estos elementos. Para obtener más información, vea Valores de configuración de Visual Studio.

Crear una interfaz

Para crear el proyecto de interfaz de equivalencia de tipos

  1. En el menú Archivo de Visual Studio, seleccione Nuevo y haga clic en Proyecto.

  2. En el cuadro de diálogo Nuevo proyecto, en el recuadro Tipos de proyecto, asegúrese de haber seleccionado Windows. En el recuadro Plantillas, seleccione Biblioteca de clases. En el cuadro Nombre, escriba TypeEquivalenceInterface y haga clic en Aceptar. Se crea el nuevo proyecto.

  3. En el Explorador de soluciones, haga clic con el botón secundario del mouse en el archivo Class1.vb o Class1.cs y haga clic en Cambiar nombre. Cambie el nombre del archivo a ISampleInterface.vb o ISampleInterface.cs y presione ENTRAR. Al cambiar el nombre del archivo también se cambiará el nombre de la clase a ISampleInterface. Esta clase representará la interfaz pública de la clase.

  4. Haga clic con el botón secundario en el proyecto TypeEquivalenceInterface y haga clic en Propiedades. Haga clic en la pestaña Compilar de Visual Basic o en la pestaña Generar de Visual C#. Establezca una ubicación válida para la ruta de acceso de salida en el equipo de desarrollo, como C:\TypeEquivalenceSample. Esta ubicación también se usará en uno de los pasos posteriores de este tutorial.

  5. Mientras se siguen editando las propiedades del proyecto, haga clic en la pestaña Firma. Seleccione la opción Firmar el ensamblado. En la lista Elija un archivo de clave de nombre seguro, haga clic en <Nuevo...>. En el cuadro Nombre del archivo de clave, escriba key.snk. Desactive la casilla Proteger mi archivo de clave mediante contraseña. Haga clic en Aceptar.

  6. Abra el archivo ISampleInterface.vb o ISampleInterface.cs. Agregue el código siguiente al archivo de clase ISampleInterface para crear la interfaz ISampleInterface.

    Imports System.Runtime.InteropServices
    
    <ComImport()>
    <Guid("8DA56996-A151-4136-B474-32784559F6DF")>
    Public Interface ISampleInterface
        Sub GetUserInput()
        ReadOnly Property UserInput As String
    
    
    ...
    
    
    End Interface
    
    using System;
    using System.Runtime.InteropServices;
    
    namespace TypeEquivalenceInterface
    {
        [ComImport]
        [Guid("8DA56996-A151-4136-B474-32784559F6DF")]
        public interface ISampleInterface
        {
            void GetUserInput();
            string UserInput { get; }
    
    
    ...
    
    
        }
    }
    
  7. En el menú Herramientas, haga clic en Crear GUID. En el cuadro de diálogo Crear GUID, haga clic en Formato del Registro y, a continuación, en Copiar. Haga clic en Salir.

  8. En el atributo Guid, elimine el GUID de ejemplo y pegue el que copió del cuadro de diálogo Crear GUID. Quite las llaves ({}) del GUID copiado.

  9. En el menú Proyecto de Visual Basic, haga clic en Mostrar todos los archivos. Omita este paso si usa Visual C#.

  10. En el Explorador de soluciones, expanda la carpeta My Project si usa Visual Basic. Expanda la carpeta Propiedades si usa Visual C#. Haga doble clic en el archivo AssemblyInfo.vb o AssemblyInfo.cs. Agregue el siguiente atributo al archivo:

    <Assembly: ImportedFromTypeLib("")> 
    
    [assembly: ImportedFromTypeLib("")]
    

    Guarde el archivo.

  11. Guarde el proyecto.

  12. Haga clic con el botón secundario en el proyecto TypeEquivalenceInterface y haga clic en Generar. El archivo .dll de la biblioteca de clases se compila y se guarda en la ruta de acceso de salida de la compilación especificada (por ejemplo, C:\TypeEquivalenceSample).

Crear una clase en tiempo de ejecución

Para crear el proyecto en tiempo de ejecución de equivalencia de tipos

  1. En el menú Archivo de Visual Studio, seleccione Nuevo y haga clic en Proyecto.

  2. En el cuadro de diálogo Nuevo proyecto, en el recuadro Tipos de proyecto, asegúrese de haber seleccionado Windows. En el recuadro Plantillas, seleccione Biblioteca de clases. En el cuadro Nombre, escriba TypeEquivalenceRuntime y haga clic en Aceptar. Se crea el nuevo proyecto.

  3. En el Explorador de soluciones, haga clic con el botón secundario del mouse en el archivo Class1.vb o Class1.cs y haga clic en Cambiar nombre. Cambie el nombre del archivo a SampleClass.vb o SampleClass.cs y presione ENTRAR. Al cambiar el nombre del archivo también se cambiará el nombre de la clase a SampleClass. Esta clase implementará la interfaz ISampleInterface.

  4. Haga clic con el botón secundario en el proyecto TypeEquivalenceRuntime y haga clic en Propiedades. Haga clic en la pestaña Compilar de Visual Basic o en la pestaña Generar de Visual C#. Establezca la ruta de acceso de salida en la misma ubicación usada en el proyecto TypeEquivalenceInterface, por ejemplo, C:\TypeEquivalenceSample.

  5. Mientras se siguen editando las propiedades del proyecto, haga clic en la pestaña Firma. Seleccione la opción Firmar el ensamblado. En la lista Elija un archivo de clave de nombre seguro, haga clic en <Nuevo...>. En el cuadro Nombre del archivo de clave, escriba key.snk. Desactive la casilla Proteger mi archivo de clave mediante contraseña. Haga clic en Aceptar.

  6. Haga clic con el botón secundario en el proyecto TypeEquivalenceRuntime y haga clic en Agregar referencia. Haga clic en la pestaña Examinar y vaya a la carpeta de la ruta de acceso de salida. Seleccione el archivo TypeEquivalenceInterface.dll y haga clic en Aceptar.

  7. En el menú Proyecto de Visual Basic, haga clic en Mostrar todos los archivos. Omita este paso si usa Visual C#.

  8. En el Explorador de soluciones, expanda la carpeta Referencias. Seleccione la referencia TypeEquivalenceInterface. En la ventana Propiedades de la referencia TypeEquivalenceInterface, establezca la propiedad Versión específica en False.

  9. Agregue el siguiente código al archivo de clase SampleClass para crear la clase SampleClass.

    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
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    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();
            }
    
    
    ...
    
    
        }
    }
    
  10. Guarde el proyecto.

  11. Haga clic con el botón secundario en el proyecto TypeEquivalenceRuntime y haga clic en Generar. El archivo .dll de la biblioteca de clases se compila y se guarda en la ruta de acceso de salida de la compilación especificada (por ejemplo, C:\TypeEquivalenceSample).

Crear un proyecto cliente

Para crear el proyecto cliente de equivalencia de tipos

  1. En el menú Archivo de Visual Studio, seleccione Nuevo y haga clic en Proyecto.

  2. En el cuadro de diálogo Nuevo proyecto, en el recuadro Tipos de proyecto, asegúrese de haber seleccionado Windows. En el recuadro Plantillas, seleccione Aplicación de consola. En el cuadro Nombre, escriba TypeEquivalenceClient y haga clic en Aceptar. Se crea el nuevo proyecto.

  3. Haga clic con el botón secundario en el proyecto TypeEquivalenceClient y haga clic en Propiedades. Haga clic en la pestaña Compilar de Visual Basic o en la pestaña Generar de Visual C#. Establezca la ruta de acceso de salida en la misma ubicación usada en el proyecto TypeEquivalenceInterface, por ejemplo, C:\TypeEquivalenceSample.

  4. Haga clic con el botón secundario en el proyecto TypeEquivalenceClient y haga clic en Agregar referencia. Haga clic en la pestaña Examinar y vaya a la carpeta de la ruta de acceso de salida. Seleccione el archivo TypeEquivalenceInterface.dll (no TypeEquivalenceRuntime.dll) y haga clic en Aceptar.

  5. En el menú Proyecto de Visual Basic, haga clic en Mostrar todos los archivos. Omita este paso si usa Visual C#.

  6. En el Explorador de soluciones, expanda la carpeta Referencias. Seleccione la referencia TypeEquivalenceInterface. En la ventana Propiedades de la referencia TypeEquivalenceInterface, establezca la propiedad Embed Interop Types en True.

  7. Agregue el código siguiente al archivo Module1.vb o Program.cs para crear el programa cliente.

    Imports TypeEquivalenceInterface
    Imports System.Reflection
    
    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
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using TypeEquivalenceInterface;
    using System.Reflection;
    
    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();
            }
        }
    }
    
  8. Presione CTRL+F5 para compilar y ejecutar el programa.

Modificar la interfaz

Para modificar la interfaz

  1. En Visual Studio, en el menú Archivo, elija Abrir y, a continuación, haga clic en Proyecto o solución.

  2. En el cuadro de diálogo Abrir proyecto, haga clic con el botón secundario en el proyecto TypeEquivalenceInterface y, a continuación, haga clic en Propiedades. Haga clic en la ficha Aplicación. Haga clic en el botón Información de ensamblado. Cambie los valores de Versión de ensamblado y Versión de archivo a 2.0.0.0.

  3. Abra el archivo ISampleInterface.vb o ISampleInterface.cs. Agregue la siguiente línea de código a la interfaz ISampleInterface.

    Function GetDate() As Date
    
    DateTime GetDate();
    

    Guarde el archivo.

  4. Guarde el proyecto.

  5. Haga clic con el botón secundario en el proyecto TypeEquivalenceInterface y haga clic en Generar. Se compila una nueva versión del archivo .dll de la biblioteca de clases y se guarda en la ruta de acceso de salida de la compilación especificada (por ejemplo, C:\TypeEquivalenceSample).

Modificar la clase en tiempo de ejecución

Para modificar la clase en tiempo de ejecución

  1. En Visual Studio, en el menú Archivo, elija Abrir y, a continuación, haga clic en Proyecto o solución.

  2. En el cuadro de diálogo Abrir proyecto, haga clic con el botón secundario en el proyecto TypeEquivalenceRuntime y haga clic en Propiedades. Haga clic en la ficha Aplicación. Haga clic en el botón Información de ensamblado. Cambie los valores de Versión de ensamblado y Versión de archivo a 2.0.0.0.

  3. Abra el archivo SampleClass.vb o SampleClass.cs. Agregue las siguientes líneas de código a la clase SampleClass.

    Public Function GetDate() As DateTime Implements ISampleInterface.GetDate
        Return Now
    End Function
    
    public DateTime GetDate()
    {
        return DateTime.Now;
    }
    

    Guarde el archivo.

  4. Guarde el proyecto.

  5. Haga clic con el botón secundario en el proyecto TypeEquivalenceRuntime y haga clic en Generar. Se compila una versión actualizada del archivo .dll de la biblioteca de clases y se guarda en la ruta de acceso de salida de la compilación especificada anteriormente (por ejemplo, C:\TypeEquivalenceSample).

  6. En el Explorador de Windows, abra la carpeta de la ruta de acceso de salida (por ejemplo, C:\TypeEquivalenceSample). Haga doble clic en TypeEquivalenceClient.exe para ejecutar el programa. El programa reflejará la nueva versión del ensamblado TypeEquivalenceRuntime sin haberse compilado de nuevo.

Vea también

Referencia

/link (Visual Basic)

/link (Opciones del compilador de C#)

Conceptos

Guía de programación de C#

Otros recursos

Guía de programación en Visual Basic

Programar con ensamblados