How to implement a event registrator which returns a winrt::event_revoker for a custom type in C++/WinRT

Viewed 54

I'm trying to add an overload to my INotifyPropertyChanged implementation for a custom type.

The base implementation for winrt::event_token is straight forward:

cpp:

winrt::event_token MyType::PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
    return propertyChanged_.add(handler);
}
void MyType::PropertyChanged(winrt::event_token const& token)
{
    propertyChanged_.remove(token);
}

h:

winrt::event_token PropertyChanged(PropertyChangedEventHandler const& value);
void PropertyChanged(winrt::event_token const& token);
winrt::event<PropertyChangedEventHandler> propertyChanged_;

where MyType is a vanilla runtimeclass

idl:

namespace Test {
    [bindable][default_interface]
    runtimeclass MyType : Microsoft.UI.Xaml.DependencyObject, Microsoft.UI.Xaml.Data.INotifyPropertyChanged

h:

namespace winrt::Test::implementation {
struct MyType : MyTypeT<MyType>

What i naively tried is to add a

int32_t unregisterPropertyChanged(winrt::event_token token);

to the header, typedef a revoker type there

using PropertyChanged_revoker = winrt::event_revoker<MyType>;

and implement the adder like this:

MyType::PropertyChanged_revoker MyType::PropertyChanged(auto_revoke_t, winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
    return PropertyChanged_revoker(get_weak(), &MyType::unregisterPropertyChanged, propertyChanged_.add(handler));
}

but it's not that easy and msvc complains about use_make_function_to_create_this_object where the instantiation causing this is here.

I couldn't find any examples and google or msdn weren't really helpful.

Since i'm not crossing abi boundaries i might be able to roll my own implementation which works around this but that feels wrong. Is there a canonical and no that involved way to do this? How to use winrt::event_revoker?

My goal is to put the revoker instances in a std::vector.

EDIT (the hacky workaround):

roll my own implementation which works around this worked; i copied the winrt event_revoker template and changed its revoke method from

void revoke() noexcept
{
    if (I object = std::exchange(m_object, {}).get())
    {
        ((*reinterpret_cast<impl::abi_t<I>**>(&object))->*(m_method))(m_token);
    }
}

to

void revoke() noexcept
{
    if (m_object.get() && m_object.get().get())
    {
        auto p = m_object.get().get();
        m_object = {};
        (p->*(m_method))(m_token);
    }
}

but it feels wrong.

0 Answers
Related