共用方式為


使用 C++/WinRT 將 Boxing 和 unboxing 值解壓縮至 IInspectable

備註

您不僅可以使用純量值,還可以使用大多數種類的陣列(但不包括列舉的陣列),透過 winrt::box_valuewinrt::unbox_value 函式來進行 boxing 和 unboxing。 您可以使用 winrt::unbox_value_or 函式,解除封裝純量值。

IInspectable 介面 是 Windows 運行時 (WinRT) 中每個執行類的根介面。 這是一個類似的概念,就像IUnknown是每個 COM 介面和類別的根,而System.Object是每個Common Type System類別的根。

換句話說,預期 IInspectable 的函式可以傳遞任何運行時間類別的實例。 但是您無法直接將純量值(例如數值或文字)傳遞給這類函式,也無法直接傳遞陣列。 相反地,純量或陣列值必須包裝在參考類別物件內。 那個包裝過程稱為 封裝 值。

這很重要

您可以封裝和解封任何可傳遞到 Windows Runtime API 的類型。 換句話說,Windows 執行階段類型。 數值和文字值(字串)和數位是上面提供的一些範例。 另一個範例是您在IDL中定義的 struct。 如果您嘗試將一個常規的 C++ struct 類型(未在 IDL 中定義)進行包裝,編譯器會提醒您只能包裝 Windows 執行階段類型。 執行階段類別是 Windows 執行階段類型,但您當然可以將執行階段類別直接傳遞給 Windows 執行階段 API,而無需對它們進行裝箱。

C++/WinRT 提供了 winrt::box_value 函數,此函數接受純量或陣列值,並將該值封裝成 IInspectable傳回。 若要將 IInspectable 解包回純量或陣列值,可以使用 winrt::unbox_value 函式。 若要將 IInspectable 復原回標量值,也可以使用 winrt::unbox_value_or 函式

Boxing 值的範例

LaunchActivatedEventArgs::Arguments 存取子函式會傳回 winrt::hstring,這是純量值。 我們可以將 hstring 值封裝之後,將它傳遞給需要 IInspectable 的函式,如下所示。

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

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

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

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

IInspectable 解包的範例

在您自行設計預期 IInspectable的函式中,可以使用 winrt::unbox_value 來進行 unbox,也可以使用 winrt::unbox_value_or 進行 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.
}

判斷封裝值的型別

如果您收到一個封箱值,且不確定其包含的類型(您需要知道其類型才能將其拆箱),那麼您可以查詢封箱值的 IPropertyValue 介面,然後在該介面上呼叫 Type 方法。 以下是程式代碼範例。

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