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
En el menú Archivo de Visual Studio, seleccione Nuevo y haga clic en Proyecto.
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.
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.
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.
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.
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; } ... } }
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.
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.
En el menú Proyecto de Visual Basic, haga clic en Mostrar todos los archivos. Omita este paso si usa Visual C#.
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.
Guarde el proyecto.
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
En el menú Archivo de Visual Studio, seleccione Nuevo y haga clic en Proyecto.
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.
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.
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.
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.
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.
En el menú Proyecto de Visual Basic, haga clic en Mostrar todos los archivos. Omita este paso si usa Visual C#.
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.
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(); } ... } }
Guarde el proyecto.
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
En el menú Archivo de Visual Studio, seleccione Nuevo y haga clic en Proyecto.
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.
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.
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.
En el menú Proyecto de Visual Basic, haga clic en Mostrar todos los archivos. Omita este paso si usa Visual C#.
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.
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(); } } }
Presione CTRL+F5 para compilar y ejecutar el programa.
Modificar la interfaz
Para modificar la interfaz
En Visual Studio, en el menú Archivo, elija Abrir y, a continuación, haga clic en Proyecto o solución.
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.
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.
Guarde el proyecto.
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
En Visual Studio, en el menú Archivo, elija Abrir y, a continuación, haga clic en Proyecto o solución.
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.
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.
Guarde el proyecto.
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).
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 (Opciones del compilador de C#)