使用 C++/WinRT,將值 Boxing 和 unboxing 處理至 IInspectable

注意

您可以使用 winrt::box_valuewinrt::unbox_value 函式,來 box 和 unbox 不只對純量值進行 box 和 unbox 處理,還可以使用大多數種類的陣列 (但列舉陣列除外)。 您可以使用 winrt::unbox_value_or 函式,將純量值 unbox。

Windows 執行階段 (WinRT) 中,IInspectable 介面是每個執行階段類別的根介面。 這是類似在每個 COM 介面與類別根的 IUnknown;以及在每個一般類型系統類別根的 System.Object 的想法。

換言之,預期 IInspectable 的函式可以傳遞任何執行階段類別的執行個體。 但是您無法直接傳遞至這類函式純量值 (例如數值或文字值),也無法直接傳遞陣列。 而是需要將純量或陣列值包裝於參考類別物件中。 該包裝程序稱為「boxing」值。

重要

您可以對任何可傳至 Windows 執行階段 API 的類型進行 Box 和 Unbox 處理。 換句話說,即 Windows 執行階段類型。 數值和文字值 (字串) 和陣列是上面提供的一些範例。 另一個範例是您在 IDL 中定義的 struct。 如果您嘗試對一般 C++ struct (未定義於 IDL 中) 進行 Box 處理,則編譯器會提醒您,您只能對 Windows 執行階段類型進行 Box 處理。 執行階段類別是一種 Windows 執行階段類型,但您理當可將執行階段類別傳至 Windows 執行階段 API,而不需要進行其 Box 處理。

C++/WinRT 提供 winrt::box_value 函式,該函式採用純量或陣列值,並傳回經過 Box 處理到 IInspectable 的值。 若要將 IInspectable unbox 回純量或陣列值,有 winrt::unbox_value 函式可選擇。 若要將 IInspectable unbox 回純量值,也有 winrt::unbox_value_or 函式。

Boxing 值的範例

LaunchActivatedEventArgs::Arguments 存取子函式傳回 winrt::hstring,即為純量數值。 我們可以 box 該 hstring 值,並將其傳遞至預期 IInspectable 的函式,如下所示。

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

若要設定 XAML 按鈕 的內容屬性,您可以呼叫 Button::Content 更動子函式。 若要將內容屬性設定為字串值,您可以使用此程式碼。

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

首先,hstring 轉換建構函式將字串常值轉換成 hstring。 然後叫用採用 hstringwinrt::box_value 多載。

Unboxing IInspectable 的範例

在您自己的預期 IInspectable 函式中,可以使用 winrt::unbox_value 來 unbox,而且可以使用 winrt::unbox_value_or 來 unbox 預設值。 您也可以使用 try_as 將 unbox 回 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.
}

判斷 Boxed 實值的類型

如果您收到 Boxed 實值,但不確定它包含哪些類型 (需要知道其類型以便 Unbox),您可以查詢 Boxed 實值的 IPropertyValue 介面,然後呼叫其類型。 以下是程式碼範例。

WINRT_ASSERT 是巨集定義,而且會發展為 _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