Compartir a través de


Conversión de tipos importados

En este tema se describe cómo el proceso de importación convierte los tipos siguientes:

  • Interfaces

  • Clases

  • Estructuras

  • Enumeraciones

  • Constantes

  • Typedefs

Por lo general, Tlbimp.exe importa los tipos con el mismo nombre que tenían en la biblioteca de tipos original. Dentro de una biblioteca de tipos, los nombres deben ser únicos para eliminar así los conflictos de nomenclatura durante el proceso de conversión. Todos los nombres de biblioteca de tipos válidos son nombres de ensamblado válidos.

Los tipos importados reciben su ámbito del espacio de nombres al que pertenecen, que es el mismo que el de la biblioteca de tipos original. Cada uno de los tipos se identifica por el nombre completo de su espacio de nombres y de su tipo.

El nombre administrado de un tipo importado se puede controlar explícitamente usando un atributo de biblioteca de tipos en dicha biblioteca. El identificador de este atributo definido por el usuario es 0F21F359-AB84-41e8-9A78-36D110E6D2F9. En la siguiente biblioteca de tipos se muestra la adición del atributo definido por el usuario.

Representación de biblioteca de tipos

[  uuid(…),
    version(1.0)
]
library AcmeLib {
    interface Widget {};
    [custom(0F21F359-AB84-41e8-9A78-36D110E6D2F9, 
     "Acme.WidgetLib.Slingshot")]
    coclass Slingshot {};
};

Aunque Tlbimp.exe importa la biblioteca de tipos en el espacio de nombres AcmeLib, la clase Slingshot se convierte en Acme.WidgetLib.Slingshot.

Interfaces

Cuando el proceso de importación convierte una interfaz, elimina todos los métodos IUnknown e IDispatch. La conversión aplica GuidAttribute a la interfaz para conservar el identificador de interfaz IID asignado en la biblioteca de tipos e InterfaceTypeAttribute, a menos que la interfaz sea dual (una interfaz derivada de IDispatch).

Representación de biblioteca de tipos

[uuid(…), ]
interface IWidget : IUnknown {
    HRESULT New()
    HRESULT Start()
};
[uuid(…), ]
interface IGadget : IWidget {
    HRESULT Baz()
};

Durante la conversión, el proceso de importación agrega los métodos de la interfaz base a la interfaz derivada. En el siguiente ejemplo, New y Start se agregan a la interfaz IGadget:

<Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IWidget
    Sub [New]()
    Sub Start()
End Interface

<Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IGadget
    Inherits IWidget
    Shadows Sub [New]()
    Shadows Sub Start()
    Sub Baz()
End Interface
[Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IWidget {
    void New();
    void Start();
};
[Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IGadget : IWidget {
    new void New();
    new void Start();
    void Baz();
};

Clases

El proceso de importación crea una clase administrada que representa a cada coclase COM y da a la clase administrada el nombre de la coclase original agregando Class. Por ejemplo, la coclase NewNewer se convierte en NewNewerClass. La conversión agrega GuidAttribute a la clase para capturar el identificador de clases (CLSID) de la coclase.

Además de la clase administrada, el proceso de importación agrega una interfaz con el mismo nombre que la coclase y aplica el CoClassAttribute para identificar el CLSID de la coclase original. La interfaz tiene el mismo IID que la interfaz predeterminada de la coclase. Con este interfaz, los clientes siempre pueden registrar mientras el evento recibe.

A diferencia de las coclases COM, las clases administradas pueden contener miembros de clase. Siguiendo el enfoque de .NET Framework, la conversión agrega a cada clase los miembros asociados a cada interfaz implementada por la coclase. Los usuarios de la clase administrada pueden invocar los métodos y propiedades del tipo administrado sin tener que efectuar antes la conversión a una interfaz concreta. El proceso de importación también puede agregar un constructor predeterminado a cada coclase convertida. Un constructor permite crear la clase desde código administrado. Las clases sin constructor no se pueden crear. El constructor predeterminado no tiene argumentos; su implementación llama al constructor de la clase base. Si se aplica a la coclase el atributo de biblioteca de tipos noncreatable, el proceso de importación no crea un constructor predeterminado para la clase.

Como los nombres de los miembros de interfaz no son siempre únicos, se pueden producir conflictos de nombres e identificadores DispId entre miembros. Tlbimp.exe resuelve los conflictos de nombres agregando como prefijo el nombre de la interfaz y un carácter de subrayado al nombre de cada miembro de la clase en conflicto. Cuando hay un conflicto entre nombres de miembros, la primera interfaz enumerada en la instrucción de la coclase se conserva sin cambios.

Si hay conflictos de identificadores DispId, el proceso de importación asigna identificadores DispId a los miembros de la interfaz predeterminada de la coclase pero no a los miembros de la clase en conflicto. Sin embargo, el proceso de importación siempre asigna identificadores DispId a los miembros de la interfaz.

Representación de biblioteca de tipos

[uuid(…)]
interface INew : IDispatch {
    [id(0x100)] HRESULT DoFirst();
    [id(0x101)] HRESULT DoSecond();
}
[uuid(…)]
interface INewer : IDispatch {
    [id(0x100)] HRESULT DoNow();
    [id(0x101)] HRESULT DoSecond();
}
[uuid(…)]
coclass NewNewer  {
    [default] interface INew;
    interface INewer;
}

Los tipos convertidos aparecen de la siguiente manera:

<Guid(…)> Public Interface INew
    …
End Interface

<Guid(…)> Public Interface INewer
    …
End Interface

<Guid(…)> Public Interface NewNewer
Inherits INew
    …
End Interface

<Guid(…)> Public Class NewNewerClass
Implements INew   
Implements INewer
Implements NewNewer
' Method implementation
     <DispId(100)> _
      …
End Class  
[Guid(…)]
public interface INew {…}

[Guid(…)]
public interface INewer {…}

[Guid(…)]
public interface NewNewer : INew {…}

[Guid(…)]
public class NewNewer : INew, INewer, NewNewer{
// Method implementation.
     [DispId(100)]…
}

Estructuras

Las estructuras definidas dentro de una biblioteca de tipos se importan como metadatos. Si un campo de una estructura es un tipo de referencia, Tlbimp.exe importa el tipo como un IntPtr y aplica ComConversionLossAttribute. El atributo indica que se ha perdido información durante el proceso de importación.

Enumeraciones

Importador de la biblioteca de tipos (Tlbimp.exe) importa enumeraciones no administradas como tipos Enum administrados.

Constantes

Las constantes no se importarán de la biblioteca de tipos en esta versión.

Typedefs

Las definiciones de tipos (typedefs) de una biblioteca de tipos no se importan. En su lugar se importan parámetros y campos como tipos subyacentes. Por ejemplo, se importa un parámetro del tipo BUTTON_COLOR como tipo entero, ya que BUTTON_COLOR es el alias de un entero.

Una vez importados, los parámetros y los campos transportan la información que los asocia a su tipo original en ComAliasNameAttribute. El proceso de conversión aplica ComAliasNameAttribute para asociar un campo, un parámetro o un valor devuelto al nombre de la biblioteca de tipos y al tipo de la biblioteca que se usó como alias.

En la siguiente representación de biblioteca de tipos se muestra que el parámetro cl tiene como tipo BUTTON_COLOR, que es el alias de un entero.

Representación de biblioteca de tipos

library MyLib {
    typedef [public] int BUTTON_COLOR;

    interface ISee {
        HResult SetColor([in] BUTTON_COLOR cl);
        HResult GetColor([out, retval] BUTTON_COLOR *cl);
    };
   
    coclass See {
        [default] interface ISee
    };
};

Los tipos convertidos aparecen de la siguiente manera:

public interface ISee {
    void SetColor([ComAliasName("MyLib.BUTTON_COLOR")]] int cl);
    [return: ComAliasName("MyLib.BUTTON_COLOR")] int GetColor();
};

public class See {
    public void SetColor([ComAliasName("MyLib.BUTTON_COLOR")]] int cl);
    [return: ComAliasName("MyLib.BUTTON_COLOR")] int GetColor();
};

Tenga en cuenta que el tipo real BUTTON_COLOR no está definido en los metadatos resultantes. En lugar de ello, los parámetros que tienen como tipo BUTTON_COLOR en la biblioteca de tipos adoptan el tipo subyacente int y se les aplica el atributo ComAliasNameAttribute. Este proceso de conversión aplica también el atributo a argumentos en los métodos de clase.

Vea también

Conceptos

Conversión de bibliotecas importadas
Conversión de módulos importados
Conversión de miembros importados
Conversión de parámetros importados

Otros recursos

Resumen de la conversión de bibliotecas de tipos en ensamblados