C++/WinRT를 사용해 값을 IInspectable로 boxing 및 unboxing
참고 항목
winrt::box_value 및 winrt:unbox_value 함수를 사용하여 스칼라 값뿐만 아니라 대부분의 배열 유형(열거 배열 제외)도 boxing 및 unboxing할 수 있습니다. winrt::unbox_value_or 함수를 사용하면 스칼라 값만 unboxing할 수 있습니다.
IInspectable 인터페이스는 Windows 런타임(WinRT)에서 모든 런타임 클래스의 루트 인터페이스입니다. 이는 IUnknown이 모든 COM 인터페이스 및 클래스의 루트에 위치하고, System.Object가 모든 공용 형식 시스템 클래스의 루트에 위치하는 것과 유사합니다.
다시 말해서 IInspectable이 필요한 함수에는 모든 런타임 클래스 인스턴스를 전달할 수 있습니다. 하지만 스칼라 값(예: 숫자 또는 텍스트 값)이나 배열을 이러한 함수로 직접 전달할 수 없습니다. 대신 스칼라 또는 배열 값을 참조 클래스 개체 안에 래핑해야 합니다. 이 래핑 프로세스에 대해 값을 boxing한다고 합니다.
Important
Windows 런타임 API에 전달할 수 있는 모든 형식을 boxing 및 unboxing할 수 있습니다. 즉, Windows 런타임 형식입니다. 숫자, 텍스트 값(문자열), 배열의 몇 가지 예가 위에 나와 있습니다. 또 다른 예제는 IDL에 정의된 struct
입니다. 일반 C++ struct
(IDL에 정의되어 있지 않음)를 boxing하려고 하면 컴파일러에서 Windows 런타임 형식만 boxing할 수 있다고 알려줍니다. 런타임 클래스는 Windows 런타임 형식이지만, boxing하지 않고 런타임 API에 전달할 수도 있습니다.
C++/WinRT는 winrt::box_value 함수를 제공합니다. 이 함수는 스칼라 또는 배열 값을 가져와 IInspectable로 boxing되는 값을 반환합니다. IInspectable을 스칼라 또는 배열 값으로 다시 unboxing하기 위해 winrt::unbox_value 함수가 있습니다. IInspectable을 스칼라 값으로 다시 unboxing하기 위해 winrt::unbox_value_or 함수도 있습니다.
값을 boxing하는 예제
LaunchActivatedEventArgs::Arguments 접근자 함수는 스칼라 값으로 winrt::hstring을 반환합니다. 이 hstring 값을 아래와 같이 boxing하여 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 오버로드가 호출됩니다.
IInspectable을 unboxing하는 예제
IInspectable이 필요한 사용자 고유의 함수에서는 winrt::unbox_value를 사용해 unboxing하거나 winrt::unbox_value_or을 사용해 기본값으로 unboxing할 수 있습니다. 또한 try_as를 사용하여 std::optional로 unboxing할 수 있습니다.
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.
}
boxing된 값 형식 확인
boxing된 값을 받았으나 이 값에 포함된 형식이 무엇인지 확실하지 않은 경우(unboxing하려면 형식을 알아야 함) 해당 IPropertyValue 인터페이스에 대해 boxing된 값을 쿼리하고 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);