Condividi tramite


Conversione boxing e unboxing dei valori in IInspectable con C++/WinRT

Annotazioni

È possibile eseguire il boxing e l'unboxing non solo di valori scalari, ma anche della maggior parte dei tipi di array (ad eccezione degli array di enumerazioni) usando le funzioni winrt::box_value e winrt::unbox_value. È possibile estrarre i valori scalari solo utilizzando la funzione winrt::unbox_value_or.

L'interfaccia IInspectable è l'interfaccia radice di ogni classe di runtime nel Windows Runtime (WinRT). Si tratta di un'idea analoga a IUnknown che sta alla base di ogni interfaccia e classe COM; e a System.Object che sta alla base di ogni classe del Common Type System.

In altre parole, una funzione che prevede IInspectable può essere passata a un'istanza di qualsiasi classe di runtime. Ma non è possibile passare direttamente a tale funzione un valore scalare (ad esempio un valore numerico o di testo) né una matrice. È invece necessario racchiudere un valore scalare o un array all'interno di un oggetto di una classe di riferimento. Il processo di incapsulamento è noto come boxing del valore.

Importante

È possibile effettuare il boxing e l'unboxing di qualsiasi tipo che si può passare a un'API di Windows Runtime. In altre parole, un tipo di Windows Runtime. I valori numerici e di testo (stringhe) e le matrici sono alcuni esempi indicati in precedenza. Un altro esempio è un struct definito in IDL. Se si tenta di eseguire la casella di un normale struct C++ (uno non definito in IDL), il compilatore vi ricorderà che è possibile boxare solo un tipo di Windows Runtime. Una classe di runtime è un tipo di Windows Runtime, ma è ovviamente possibile passare classi di runtime alle API di Windows Runtime senza boxing.

C++/WinRT fornisce la funzione winrt::box_value, che accetta un valore scalare o di array e restituisce il valore incapsulato in un IInspectable. Per l'unboxing di un IInspectable in un valore scalare o di matrice, esiste la funzione winrt::unbox_value. Per effettuare l'unboxing di un IInspectable in un valore scalare, esiste anche la funzione winrt::unbox_value_or.

Esempi di boxing di un valore

La funzione di accesso LaunchActivatedEventArgs::Arguments restituisce un winrt::hstring, che è un valore scalare. È possibile fare il boxing di quel valore hstring e passarlo a una funzione che si aspetta un IInspectable come questo.

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

Per impostare la proprietà del contenuto di un ButtonXAML, è necessario chiamare la funzione modificatore Button::Content. Per impostare la proprietà content su un valore stringa, è possibile usare questo codice.

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

Prima di tutto, il costruttore di conversione hstring converte il valore letterale stringa in un hstring. Viene quindi richiamato l'overload di winrt::box_value che accetta un hstring.

Esempi di spacchettamento di un IInspectable

Nelle proprie funzioni che prevedono IInspectable, è possibile usare winrt::unbox_value per estrarre il valore ed è possibile usare winrt::unbox_value_or per estrarre il valore con un valore predefinito. È anche possibile usare try_as per estrarre il valore in 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.
}

Determinare il tipo di un valore incapsulato

Se si riceve un valore boxed e non si è certi del tipo che contiene (è necessario conoscerne il tipo per annullarne la conversione), è possibile eseguire una query sul valore boxed per l'interfaccia IPropertyValue e quindi chiamare Type su di esso. Ecco un esempio di codice.

WINRT_ASSERT è una definizione di macro e si espande fino 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 importanti