使用 C++/WinRT,將值 Boxing 和 unboxing 處理至 IInspectable
注意
您可以使用 winrt::box_value 和 winrt::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。 然後叫用採用 hstring 的 winrt::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);