Nilai tinju dan pembukaan kotak ke IInspectable dengan C++/WinRT

Catatan

Anda dapat membuat kotak dan membuka kotak tidak hanya nilai skalar, tetapi juga sebagian besar jenis array (dengan pengecualian array enumerasi) dengan menggunakan fungsi winrt::box_value dan winrt::unbox_value. Anda hanya dapat membuka kotak nilai skalar dengan menggunakan fungsi winrt::unbox_value_or .

Antarmuka IInspectable adalah antarmuka akar dari setiap kelas runtime di Windows Runtime (WinRT). Ini adalah ide analog untuk IUnknown berada di akar setiap antarmuka dan kelas COM; dan System.Object berada di akar setiap kelas Common Type System.

Dengan kata lain, fungsi yang mengharapkan IInspectable dapat diteruskan instans dari kelas runtime apa pun. Tetapi Anda tidak dapat langsung meneruskan ke fungsi seperti itu nilai skalar (seperti nilai numerik atau teks), atau array. Sebagai gantinya, nilai skalar atau array perlu dibungkus di dalam objek kelas referensi. Proses pembungkusan itu dikenal sebagai tinju nilai.

Penting

Anda dapat mengetik dan membuka kotak jenis apa pun yang dapat Anda teruskan ke Windows Runtime API. Dengan kata lain, jenis Windows Runtime. Nilai numerik dan teks (string), dan array, adalah beberapa contoh yang diberikan di atas. Contoh lain adalah struct yang Anda tentukan dalam IDL. Jika Anda mencoba menkotak C++ struct reguler (yang tidak ditentukan dalam IDL), pengkompilasi akan mengingatkan Anda bahwa Anda hanya dapat menkotak jenis Windows Runtime. Kelas runtime adalah jenis Windows Runtime, tetapi Anda tentu saja dapat meneruskan kelas runtime ke WINDOWS Runtime API tanpa metinjunya.

C++/WinRT menyediakan fungsi winrt::box_value, yang mengambil nilai skalar atau array, dan mengembalikan nilai yang dikotak ke dalam IInspectable. Untuk membuka kotak IInspectable kembali ke nilai skalar atau array, ada fungsi winrt::unbox_value. Untuk membuka kotak IInspectable kembali ke nilai skalar, ada juga fungsi winrt::unbox_value_or.

Contoh tinju nilai

Fungsi pengaktif LaunchActivatedEventArgs::Arguments mengembalikan winrt::hstring, yang merupakan nilai skalar. Kita dapat menkotak nilai hstring itu dan meneruskannya ke fungsi yang mengharapkan IInspectable seperti ini.

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

Untuk mengatur properti konten Tombol XAML, Anda memanggil fungsi Mutator Tombol::Konten. Untuk mengatur properti konten ke nilai string, Anda dapat menggunakan kode ini.

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

Pertama, konstring konversi hstring mengonversi string harfiah menjadi hstring. Kemudian kelebihan beban winrt::box_value yang mengambil hstring dipanggil.

Contoh pembukaan kotak IInspectable

Dalam fungsi Anda sendiri yang mengharapkan IInspectable, Anda dapat menggunakan winrt::unbox_value untuk membuka kotak, dan Anda dapat menggunakan winrt::unbox_value_or untuk membuka kotak dengan nilai default. Anda juga dapat menggunakan try_as untuk membuka kotak ke std::opsional.

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.
}

Menentukan jenis nilai berkotak

Jika Anda menerima nilai kotak dan tidak yakin jenis apa yang dikandungnya (Anda perlu mengetahui jenisnya untuk membuka kotaknya), maka Anda dapat mengkueri nilai kotak untuk antarmuka IPropertyValue-nya, lalu memanggil Jenis di atasnya. Berikut adalah contoh kode.

WINRT_ASSERT adalah definisi makro, dan meluas ke _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 penting