Atributos predefinidos (MIDL 3.0)

Hay una serie de atributos personalizados predefinidos que permiten controlar el nombre y el identificador de interfaz (IID) para las interfaces sintetizadas por el compilador. Estos atributos permiten controlar el control de versiones y la API binaria de la clase en un nivel específico.

Si es un desarrollador de componentes o un autor de biblioteca, puede que desee usar estos atributos para asegurarse de que los componentes permanecen binarios estables de una versión a la siguiente.

Si es un desarrollador de aplicaciones, en general no tendrá que usar estos atributos porque volverá a compilar la aplicación después de revisar los tipos.

Atributo [allowforweb]

Para obtener más información sobre el uso y el propósito del allowforweb atributo, vea la clase AllowForWebAttribute.

Atributo [constructor_name]

El constructor_name atributo especifica el nombre y el IID de la interfaz de generador que contiene los miembros del constructor. Consulte Synthesizing interfaces (Síntesis de interfaces ) para obtener más información sobre las interfaces de fábrica.

Nota

Una interfaz de generador solo es aplicable a una clase sellada con constructores no predeterminados o a una clase sin sellar con constructores predeterminados o no predeterminados.

En el ejemplo siguiente, el constructor Block protegido se coloca en la interfaz IBlockFactory y esa interfaz tiene el IID especificado.

[constructor_name("Windows.UI.Xaml.Documents.IBlockFactory", 07110532-4f59-4f3b-9ce5-25784c430507)]
...
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    protected Block();
    ...
}

Como resultado, cuando la descripción de la clase no hace referencia a una interfaz, pero cuando se necesita una para implementar la clase, el compilador de MIDL 3.0 sintetiza y agrega interfaces, según sea necesario.

Atributo [contentproperty]

el contentproperty atributo representa la clase ContentPropertyAttribute . Este es un ejemplo:

// BgLabelControl.idl
namespace BgLabelControlApp
{
    [contentproperty("Content")]
    runtimeclass BgLabelControl : Windows.UI.Xaml.Controls.Control
    {
        BgLabelControl();
        static Windows.UI.Xaml.DependencyProperty LabelProperty{ get; };
        String Label;
        static Windows.UI.Xaml.DependencyProperty ContentProperty{ get; };
        IInspectable Content;
    }
}

Atributo [contract]

No use el atributo contract en sus propias API; solo tiene significado para las API Windows integradas.

contract El atributo especifica el nombre y la versión del contrato de API de Windows 10 (consulte Programación con SDK de extensión) en el que el tipo o miembro con atributos se introdujo por primera vez en Windows (por lo tanto, no es significativo para las API no entregadas como parte de Windows). El atributo toma la forma [contract(ContractName, ContractVersion)]y aparece delante del elemento al que se aplica.

Atributo [default]

Si no especifica una interfaz predeterminada, el compilador de MIDL 3.0 elige la primera interfaz de instancia. Para invalidar esta selección, inserte el atributo default antes de la interfaz que desea que sea la interfaz predeterminada.

// Declaring an external interface as the default
runtimeclass C : [default]I { ... }

// Declaring a specific exclusiveto interface as the default.
// This is very unusual.
runtimeclass C
{
    ...

    [default][interface_name(...)]
    {
        ...
    }
}

Atributo [default_interface]

El default_interface atributo se usa para forzar la generación de una interfaz predeterminada en la que no se generaría otro. En el ejemplo siguiente, StateTriggerBase no necesita una interfaz predeterminada (porque no tiene miembros públicos no estáticos), default_interface por lo que es solo la presencia del atributo la que hace que se genere uno (denominado IStateTriggerBase).

[default_interface]
unsealed runtimeclass StateTriggerBase
{
    protected void SetActive(Boolean IsActive);
};

Atributo [default_overload]

Nota

Este atributo no se admite para constructores. Si no puede sobrecargar los constructores por arity, puede definir métodos de generador sobrecargados, como los ejemplos CreateFromUri y CreateFromStream que se muestran en el último fragmento de código de esta sección.

El default_overload atributo representa la clase DefaultOverloadAttribute , que indica que un método es el método de sobrecarga predeterminado. En esta sección se le guiará por el motivo y las directrices de uso del [default_overload] atributo.

Puede sobrecargar libremente Windows Runtime métodos por arity. Es decir, puede definir varios métodos con el mismo nombre, siempre y cuando cada uno de ellos tome un número diferente de argumentos. Para fines de facilidad de uso, se recomienda agregar nuevos parámetros al final y que el comportamiento de la función shorter-parameter-list sea equivalente a llamar a la función longer-parameter-list con valores predeterminados naturales (específicos del escenario) para los parámetros que faltan.

runtimeclass Widget
{
    void Start();
    void Start(StartMode mode);
    void Start(StartMode mode, Widget parent);
}

En el ejemplo anterior, se puede llamar a Start con dos parámetros para especificar un modo de inicio y un widget primario. Si omite el widget primario, el valor predeterminado es NULL. Y si omite el modo, se inicia en algún modo predeterminado específico del escenario.

En este ejemplo siguiente se usa DeviceInformation.CreateWatcher .

runtimeclass DeviceInformation
{
    static DeviceWatcher CreateWatcher();
    static DeviceWatcher CreateWatcher(DeviceClass deviceClass);
    static DeviceWatcher CreateWatcher(String aqsFilter);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties,
                                       DeviceInformationKind kind);
}

En ese ejemplo hay cinco sobrecargas y la mayoría de ellas siguen el patrón recomendado de que cada nueva sobrecarga sea una extensión de la sobrecarga anterior.

Si decide tener varias sobrecargas de un método con el mismo número de parámetros, se producirá un error del compilador:

Las sobrecargas de 1 parámetro de DeviceInformation.CreateWatcher deben tener exactamente un método especificado como sobrecarga predeterminada decorando con Windows. Foundation.Metadata.DefaultOverloadAttribute.

El motivo es que algunos lenguajes de programación se escriben dinámicamente. JavaScript y Python son dos ejemplos. Para estos lenguajes, la selección de la sobrecarga solo tiene en cuenta el número de parámetros y no sus tipos. Esto significa que una llamada de JavaScript DeviceInformation.createWatcher(v); a es ambigua: ¿se debe coercir v a una clase DeviceClass o a una cadena?

Para resolver la ambigüedad, debe aplicar el [default_overload] atributo a uno de los métodos . Pero, ¿cómo se elige cuál?

Debe elegir la sobrecarga predeterminada para que la funcionalidad de las sobrecargas no predeterminadas todavía esté disponible por otros medios, normalmente por una de las otras sobrecargas.

En el ejemplo DeviceInformation.CreateWatcher, la funcionalidad de la sobrecarga String se puede obtener llamando a la sobrecarga String, IIterableString<> y pasando una lista vacía de propiedades. Por otro lado, la sobrecarga DeviceClass es la única manera de crear un DeviceWatcher que se filtra por DeviceClass.

Esto hace que el método DeviceClass sea el ganador claro. Por lo tanto, debe indicarlo aplicando el atributo [default_overload] a esa sobrecarga.

runtimeclass DeviceInformation
{
    static DeviceWatcher CreateWatcher();
    [default_overload]
    static DeviceWatcher CreateWatcher(DeviceClass deviceClass);
    static DeviceWatcher CreateWatcher(String aqsFilter);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties,
                                       DeviceInformationKind kind);
}

¿Qué ocurre si no hay ningún ganador porque todas las sobrecargas en conflicto proporcionan una funcionalidad única que no está disponible en otras sobrecargas?

runtimeclass Widget
{
    static Widget Create(Uri source);
    static Widget Create(IInputStream source);
}

Nuestro hipotético objeto Widget se puede crear a partir de un URI o a partir de un flujo de entrada. Si marcamos uno como sobrecarga predeterminada, los lenguajes de programación con tipo dinámico perderán completamente el acceso al otro.

Para solucionar este problema, dé a las dos versiones nombres diferentes para que no se sobrecarguen.

runtimeclass Widget
{
    static Widget CreateFromUri(Uri source);
    static Widget CreateFromStream(IInputStream source);
}

Ahora ambos patrones de creación están disponibles para todos los idiomas.

Vea también Sobrecarga de métodos y Proyección basada en clases.

Atributo [interface_name]

El interface_name atributo especifica el nombre y el IID de la interfaz que contiene los miembros de instancia de la clase . De forma predeterminada, el compilador asigna nombres de interfaz con el mismo algoritmo de numeración único que usa para los métodos.

En el ejemplo siguiente, interface_name el atributo aplicado a la clase runtimeclass especifica el nombre y el IID de la interfaz que contiene todos los miembros de instancia de la clase que no están asignados de otro modo a una interfaz. Por lo tanto, LineHeight, LineStackingStrategy, Margin y TextAlignment son miembros de la interfaz IBlock .

Sin embargo, HorizontalTextAlignment es miembro de la interfaz IBlock2 , interface_name debido al atributo que abarca ese miembro.

[interface_name("Windows.UI.Xaml.Documents.IBlock", 4bce0016-dd47-4350-8cb0-e171600ac896)]
...
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    Double LineHeight;
    Windows.UI.Xaml.LineStackingStrategy LineStackingStrategy;
    Windows.UI.Xaml.Thickness Margin;
    Windows.UI.Xaml.TextAlignment TextAlignment;

    [interface_name("Windows.UI.Xaml.Documents.IBlock2", 5ec7bdf3-1333-4a92-8318-6caedc12ef89)]
    {
        Windows.UI.Xaml.TextAlignment HorizontalTextAlignment;
    }
    ...
}

También puede usar el atributo para interface_name forzar la generación de una interfaz. En el ejemplo siguiente, StateTriggerBase no necesita IStateTriggerBase y interface_name es solo la presencia del atributo lo que hace que se genere.

[interface_name("Windows.UI.Xaml.IStateTriggerBase", 48b20698-af06-466c-8052-93666dde0e49)]
unsealed runtimeclass StateTriggerBase
{
    protected void SetActive(Boolean IsActive);
};

Como resultado, cuando la descripción de la clase no hace referencia a una interfaz, pero cuando se necesita una para implementar la clase, el compilador de MIDL 3.0 sintetiza y agrega interfaces, según sea necesario.

Si usa innecesariamente default_interface , MIDL 3.0 genera una interfaz vacía adicional y hace que sea el valor predeterminado.

Atributo [method_name]

Cada Windows Runtime interfaz tiene una interfaz de interfaz binaria de aplicación (ABI) equivalente. La interfaz ABI requiere que todos los miembros tengan nombres únicos. Hay dos casos en MIDL 3.0 en los que los miembros no tienen un nombre o no tienen un nombre único.

  • constructores, y
  • dos o más métodos sobrecargados.

En estos casos, el compilador de MIDL 3.0 sintetiza un nombre de miembro único, según sea necesario.

De forma predeterminada, el compilador asigna a los métodos de constructor < los nombres className>, <className2>, <className3>, y así sucesivamente para los métodos equivalentes en la interfaz ABI. En otras palabras, se agrega el sufijo numérico entero sin usar más pequeño (aumentando de 2) para que el nombre del método constructor sea único.

Del mismo modo, para los métodos sobrecargados, para el primer método de una serie de sobrecargas (en orden léxico), el compilador usa el nombre de método original para el método de interfaz ABI equivalente. Las sobrecargas posteriores se hacen únicas agregando al nombre original el sufijo numérico entero sin usar más pequeño (aumentando de 2).

Por ejemplo, el siguiente IDL declara tres sobrecargas de DoWork y dos sobrecargas de un método diferente denominado DoWork3.

void DoWork(Int32 x);
void DoWork3(Int32 x);
void DoWork(Int32 x, Int32 y);
void DoWork(Int32 x, Int32 y, Int32 z);
void DoWork3(Int32 x, Int32 y);

De forma predeterminada (puesto que ya se ha tomado el nombre DoWork3 ), el compilador proporciona los nombres a las tres sobrecargas de DoWork .

  • DoWork
  • DoWork2
  • DoWork4.

DoWork3 no es unasobrecarga de DoWork . De forma predeterminada, el compilador proporciona a las dos sobrecargas de DoWork3 los nombres

  • DoWork3
  • DoWork32.

En orden de vtable, las funciones aparecerán como

  • DoWork
  • DoWork3
  • DoWork2
  • DoWork4
  • DoWork32

Puede invalidar la asignación de nombre predeterminada del compilador mediante el method_name atributo .

En este ejemplo siguiente, se indica al compilador que use el nombre CreateInstance para el miembro del constructor predeterminado Block.

unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    [method_name("CreateInstance")] protected Block();
    ...
}

Atributo [static_name]

El static_name atributo especifica el nombre y el IID de la interfaz que contiene miembros estáticos de la clase .

En este ejemplo siguiente, static_name el atributo aplicado a runtimeclass especifica el nombre y el IID de la interfaz que contiene todos los miembros estáticos de la clase que no están asignados de otro modo a una interfaz. Por lo tanto, LineHeightProperty, LineStackingStrategyProperty, MarginProperty y TextAlignmentProperty son miembros de la interfaz IBlockStatics .

Sin embargo, HorizontalTextAlignmentProperty es miembro de la interfaz IBlockStatics2 , static_name debido al atributo que abarca ese miembro.

[static_name("Windows.UI.Xaml.Documents.IBlockStatics", f86a8c34-8d18-4c53-aebd-91e610a5e010)]
...
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    static Windows.UI.Xaml.DependencyProperty LineHeightProperty{ get; };
    static Windows.UI.Xaml.DependencyProperty LineStackingStrategyProperty{ get; };
    static Windows.UI.Xaml.DependencyProperty MarginProperty{ get; };
    static Windows.UI.Xaml.DependencyProperty TextAlignmentProperty{ get; };

    [static_name("Windows.UI.Xaml.Documents.IBlockStatics2", af01a4d6-03e3-4cee-9b02-2bfc308b27a9)]
    {
        static Windows.UI.Xaml.DependencyProperty HorizontalTextAlignmentProperty{ get; };
    }
    ...
}