Compartir a través de


Conversión de valores mediante encapsulado y desencapsulado a IInspectable con C++/WinRT

Nota:

Puede encapsular y desencapsular no solo valores escalares, sino también la mayoría de tipos de matrices, excepto matrices de enumeraciones, mediante las funciones winrt::box_value y winrt::unbox_value. Solo se pueden quitar los valores escalares mediante la función winrt::unbox_value_or de .

La interfaz IInspectable es la interfaz raíz de cada clase de Windows Runtime (WinRT). Esta es una idea análoga a IUnknown estar en la raíz de cada interfaz y clase COM; y System.Object estar en la raíz de cada clase Common Type System.

Es decir, a una función que espera un IInspectable se le puede pasar una instancia de cualquier clase de tiempo de ejecución. Pero no se puede pasar directamente a esta función un valor escalar (como un valor numérico o de texto), ni una matriz. En su lugar, es necesario encapsular un valor escalar o de matriz dentro de un objeto de clase referencial. Ese proceso de envoltura se conoce como encapsulación del valor.

Importante

Puedes empaquetar y desempaquetar cualquier tipo que puedas pasar a una API de Windows Runtime. En otras palabras, un tipo de Windows Runtime. Los valores numéricos y de texto (cadenas) y las matrices son algunos ejemplos anteriores. Otro ejemplo es un struct que tú defines en IDL. Si intentas boxear un struct normal de C++ (uno que no está definido en IDL), el compilador te recordará que solo puedes boxear un tipo de Windows Runtime. Una clase de tiempo de ejecución es un tipo de Windows Runtime, pero, por supuesto, puede pasar clases de tiempo de ejecución a las API de Windows Runtime sin necesidad de boxing.

de C++/WinRT proporciona la función winrt::box_value de , que toma un valor escalar o de matriz, y devuelve el valor en un IInspectable . Para desempaquetar una IInspectable en un valor escalar o un valor de matriz, existe la función winrt::unbox_value. Para deshacer una IInspectable en un valor escalar, también existe la función winrt::unbox_value_or.

Ejemplos de boxing de un valor

La función de descriptor de acceso LaunchActivatedEventArgs::Arguments devuelve un winrt::hstring, que es un valor escalar. Podemos empaquetar ese valor de hstring y pasarlo a una función que espera IInspectable así.

void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
    ...
    rootFrame.Navigate(winrt::xaml_typename<BlankApp1::MainPage>(), winrt::box_value(e.Arguments()));
    ...
}

Para establecer la propiedad Content de un Buttonen XAML, se utiliza la función de modificación Button::Content. Para establecer la propiedad content en un valor de cadena, puede usar este código.

Button().Content(winrt::box_value(L"Clicked"));

Primero, el constructor de conversión hstring convierte el literal de cadena en un hstring. A continuación, se invoca la sobrecarga de winrt::box_value que toma un hstring.

Ejemplos de unboxing de IInspectable

En tus propias funciones que esperan IInspectable, puedes usar winrt::unbox_value para realizar desempaquetado y puedes usar winrt::unbox_value_or para realizar desempaquetado con un valor predeterminado. También puede usar try_as para desempaquetar a un std::optional.

void Unbox(winrt::Windows::Foundation::IInspectable const& object)
{
    hstring hstringValue = unbox_value<hstring>(object); // Throws if object is not a boxed string.
    hstringValue = unbox_value_or<hstring>(object, L"Default"); // Returns L"Default" if object is not a boxed string.
    float floatValue = unbox_value_or<float>(object, 0.f); // Returns 0.0 if object is not a boxed float.
    std::optional<int> optionalInt = object.try_as<int>(); // Returns std::nullopt if object is not a boxed int.
}

Determinar el tipo de un valor empaquetado

Si recibe un valor empaquetado y no está seguro de qué tipo contiene (necesita conocer su tipo para desempaquetarlo), entonces puede interrogar al valor empaquetado para su interfaz IPropertyValue y luego llamar a Type en este. Este es un ejemplo de código.

WINRT_ASSERT es una definición de macro y se expande a _ASSERTE.

float pi = 3.14f;
auto piInspectable = winrt::box_value(pi);
auto piPropertyValue = piInspectable.as<winrt::Windows::Foundation::IPropertyValue>();
WINRT_ASSERT(piPropertyValue.Type() == winrt::Windows::Foundation::PropertyType::Single);

API importantes