C++/WinRT を使用した IInspectable への値のボックス化とボックス化解除
注意
winrt::box_value および winrt::unbox_value 関数を使用すると、スカラー値だけでなく、ほとんどの種類の配列 (列挙体の配列を除く) をボックス化またはボックス化解除できます。 スカラー値のみをボックス化解除するには、winrt::unbox_value_or 関数を使用します。
IInspectable インターフェイス は、Windows ランタイム (WinRT) のすべてのランタイム クラスのルート インターフェイスです。 これは、すべての COM インターフェイスとクラスのルートである IUnknown や、すべての 共通型システム クラスのルートである System.Object と似た概念です。
つまり、IInspectable を想定している関数は、任意のランタイム クラスのインスタンスに渡すことができます。 ただし、そのような関数に、スカラー値 (数値、テキスト値など) や配列を直接渡すことはできません。 代わりに、スカラーまたは配列値を参照クラス オブジェクト内にラップする必要があります。 このラッピング プロセスは、値の ボックス化 と呼ばれます。
重要
Windows ランタイム API に渡すことができる型はどれでもボックス化とボックス化解除を行うことができます。 つまり、Windows ランタイム型です。 上記の例には、数値とテキスト値 (文字列)、配列があります。 別の例として、IDL で定義する struct
があります。 通常の C++ struct
(IDL で定義されていないもの) をボックス化しようとすると、ボックス化できるのは Windows ランタイム型のみであることがコンパイラから通知されます。 ランタイム クラスは Windows ランタイム型ですが、もちろん、ランタイム クラスはボックス化せずに Windows ランタイム API に渡すことができます。
C++/WinRT には、スカラーまたは配列値を取得し、ボックス化した値を IInspectable へ返す winrt::box_value 関数が用意されています。 IInspectable をボックス化解除してスカラーまたは配列値に戻すには、winrt::unbox_value 関数があります。 また、IInspectable をボックス化解除してスカラー値に戻すには、winrt::unbox_value_or 関数があります。
値をボックス化する例
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 のコンテンツ プロパティを設定するには、Button::Content ミューテーター関数を呼び出します。 コンテンツのプロパティを文字列値に設定するには、このコードを使用できます。
Button().Content(winrt::box_value(L"Clicked"));
まず、hstring 変換コンストラクターが文字列リテラルを hstring に変換します。 次に hstring を受け取る winrt::box_value のオーバーロードが呼び出されます。
IInspectable をボックス化解除する例
IInspectable を想定する独自の関数では、winrt::unbox_value を使用してボックス化解除することができます。また winrt::unbox_value_or を使用して既定値でボックス化解除することができます。 また、try_as を使用して 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);