Compartilhar via


Valores de boxing e unboxing para IInspectable com C++/WinRT

Observação

Você pode caixa e unbox não apenas valores escalares, mas também a maioria dos tipos de matrizes (com exceção de matrizes de enumerações) usando as funções winrt::box_value e winrt::unbox_value. Você pode desencaixar apenas valores escalares usando a função winrt::unbox_value_or.

O interface IInspectable é a interface raiz de cada classe de runtime no WinRT (Windows Runtime). Essa é uma ideia análoga para IUnknown estar na raiz de cada interface e classe COM; e System.Object estar na raiz de cada classe Common Type System.

Em outras palavras, uma função que espera IInspectable pode receber uma instância de qualquer classe de tempo de execução. Mas você não pode passar diretamente para essa função um valor escalar (como um valor numérico ou de texto), nem uma matriz. Em vez disso, um valor escalar ou de matriz precisa ser encapsulado dentro de um objeto de classe de referência. Esse processo de encapsulamento é conhecido como boxing o valor.

Importante

Você pode encapsular e desencapsular qualquer tipo que possa passar para uma API do Windows Runtime. Em outras palavras, um tipo do Windows Runtime. Valores numéricos e de texto (cadeias de caracteres) e matrizes são alguns exemplos fornecidos acima. Outro exemplo é um struct que você define no IDL. Se você tentar encapsular um struct comum em C++ (um que não é definido em IDL), o compilador lembrará que você só pode encapsular um tipo do Windows Runtime. Uma classe de tempo de execução é um tipo do Windows Runtime, mas é claro que você pode passar classes de tempo de execução para APIs do Windows Runtime sem convertê-las em objetos.

C++/WinRT fornece a função winrt::box_value, que recebe um valor escalar ou de matriz e retorna o valor caixado em um IInspectable. Para desencaixar um IInspectable de volta em um valor escalar ou de matriz, existe a função winrt::unbox_value. Para converter um IInspectable de volta em um valor escalar, há também a função winrt::unbox_value_or.

Exemplos de boxing de valor

A função acessadora LaunchActivatedEventArgs::Arguments retorna um winrt::hstring , que é um valor escalar. Podemos encapsular o valor de hstring e passá-lo para uma função que espera IInspectable desta forma.

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

Para definir a propriedade de conteúdo de um botão XAML , chame a função modificadora Button::Content . Para definir a propriedade de conteúdo como um valor de cadeia de caracteres, você pode usar esse código.

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

Primeiro, o construtor de conversão de hstring converte o literal da cadeia de caracteres em um hstring . Em seguida, a sobrecarga de winrt::box_value que usa uma de hstring é invocada.

Exemplos de unboxing de um IInspectable

Em suas próprias funções que esperam IInspectable, você pode usar winrt::unbox_value para desmarcar e usar winrt::unbox_value_or para desmarcar com um valor padrão. Você também pode usar try_as para desencaixotar em um 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 o tipo de um valor encapsulado

Se você receber um valor encapsulado e não tiver certeza de qual tipo ele contém (você precisa saber seu tipo para desacoplá-lo), então poderá consultar o valor encapsulado para sua interface IPropertyValue e, em seguida, chamar Type sobre ela. Aqui está um exemplo de código.

WINRT_ASSERT é uma definição de macro e se expande para _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);

APIs importantes