Att boxa och avboxa värden till IInspectable med C++/WinRT

Note

Du kan boxa och ta bort inte bara skalära värden, utan även de flesta typer av matriser (med undantag för uppräkningsmatriser) med hjälp av funktionerna winrt::box_value och winrt::unbox_value . Du kan endast ta bort skalära värden med hjälp av funktionen winrt::unbox_value_or .

IInspectable-gränssnittet är rotgränssnittet för varje körningsklass i Windows Runtime (WinRT). Det här är en liknande idé som att IUnknown är roten till varje COM-gränssnitt och -klass. och System.Object finns i roten för varje Common Type System-klass .

Med andra ord kan en funktion som förväntar sig IInspectable ta emot en instans av valfri körningsklass. Men du kan inte direkt skicka till en sådan funktion ett skalärt värde (till exempel ett numeriskt värde eller textvärde) eller en matris. I stället måste ett skalärt värde eller matrisvärde omslutas i ett referensklassobjekt. Den omslutningsprocessen kallas boxning av värdet.

Viktigt!

Du kan boxa och avboxa valfri typ som du kan skicka till ett API i Windows Runtime. Med andra ord, en Windows Runtime-typ. Numeriska värden och textvärden (strängar) och matriser är några exempel som anges ovan. Ett annat exempel är ett struct som du definierar i IDL. Om du försöker boxa en vanlig C++ struct (en som inte har definierats i IDL) kommer kompilatorn att påminna dig om att du bara kan ange en Windows Runtime typ. En runtimeklass är en Windows Runtime-typ, men du kan förstås skicka runtimeklasser till Windows Runtime-API:er utan att boxa dem.

C++/WinRT tillhandahåller funktionen winrt::box_value, som tar ett skalärt värde eller ett arrayvärde och returnerar värdet paketerat i en IInspectable. För att avboxa en IInspectable tillbaka till ett skalärt eller matrisvärde finns funktionen winrt::unbox_value . Om du vill avboxa en IInspectable tillbaka till ett skalärt värde finns även funktionen winrt::unbox_value_or .

Exempel på boxning av ett värde

Accessor-funktionen LaunchActivatedEventArgs::Argumentsreturnerar en winrt::hstring, som är ett skalärt värde. Vi kan boxa det hstring-värdet och skicka det till en funktion som förväntar sig att IInspectable ska se ut så här.

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

Om du vill ange innehållsegenskapen för en XAML-knapp anropar du funktionen Button::Content mutator. Om du vill ange innehållsegenskapen till ett strängvärde kan du använda den här koden.

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

Först konverterar konverteringskonstruktorn för hstring strängliteralen till en hstring. Därefter anropas överlagringen av winrt::box_value som tar emot en hstring.

Exempel på att avboxa en IInspectable

I dina egna funktioner som förväntar sig IInspectable kan du använda winrt::unbox_value för att avboxa, och du kan använda winrt::unbox_value_or för att avboxa med ett standardvärde. Du kan också använda try_as för att packa upp som en 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.
}

Fastställa typen av ett rutat värde

Om du får ett boxat värde och är osäker på vilken typ det innehåller (du måste känna till typen för att kunna unboxa det), kan du fråga det boxade värdet efter dess IPropertyValue-gränssnitt och sedan anropa Type på det. Här är ett kodexempel.

WINRT_ASSERT är en makrodefinition och expanderas till _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);

Viktiga API:er