Events C++;托管事件的Cli实现

Events C++;托管事件的Cli实现,events,c++-cli,Events,C++ Cli,我想在cli/c++组件中实现一个托管接口。假设我的界面有这样一个事件: public interface IManagedInterface { event EventHandler<ServiceCollectionChangedEventArgs> ServiceCollectionChanged; } 公共接口IManagedInterface { 事件处理程序ServiceCollectionChanged; } 存在头文件和.cpp文件的My cli组件。在我的

我想在cli/c++组件中实现一个托管接口。假设我的界面有这样一个事件:

public interface IManagedInterface
{
   event EventHandler<ServiceCollectionChangedEventArgs> ServiceCollectionChanged;
}
公共接口IManagedInterface
{
事件处理程序ServiceCollectionChanged;
}
存在头文件和.cpp文件的My cli组件。在我的标题中,我定义了事件和一个私有方法来引发它

ref class NativeImplementation : public IManagedInterface
{
  public:
     virtual event System::EventHandler<ServiceCollectionChangedEventArgs^>^ ServiceCollectionChanged;

  private:
    void RaiseServiceCollectionChanged(System::Type^ type, ChangeAction action);
};
ref类本地实现:公共IManagedInterface
{
公众:
虚拟事件系统::EventHandler^ServiceCollectionChanged;
私人:
作废RaiseServiceCollectionChanged(系统::类型^Type,ChangeAction);
};
在我的.cpp文件中,我想实现raise方法,而这正是我努力的方向

void NativeImplementation::RaiseServiceCollectionChanged(Type^ type, ChangeAction action)
      {
        EventHandler<ServiceCollectionChangedEventArgs^>^ local = NativeImplementation::ServiceCollectionChanged;
        if (local != nullptr) {
          local(this, gcnew ServiceCollectionChangedEventArgs(type, action));
        }
      }
}
void NativeImplementation::RaiseServiceCollectionChanged(类型^Type,ChangeAction)
{
EventHandler^local=NativeImplementation::ServiceCollectionChanged;
如果(本地!=nullptr){
本地(这是gcnew ServiceCollectionChangedEventArgs(类型、操作));
}
}
}
我习惯于在引发事件之前进行上述检查,但编译器抱怨“错误无效使用事件成员”。有人能帮我吗?在C++中,我甚至需要这些检查吗? 感谢

在C#中,引发事件的习惯用法是将事件复制到局部变量,检查是否为null,然后使用局部变量调用处理程序,而不是重新读取事件对象

// C# Idiom
void RaiseEvent()
{
    EventHandler<Whatever> handler = this.MyEvent;
    if (handler != null)
        handler(this, new Whatever());
}

在引擎盖下,C#为每个事件成员定义了两个方法:
add
remove
,在使用
+=
-=
时调用。上面的习惯用法是必要的,因为没有内置的null检查,并且如果在null检查和实际触发事件之间的另一个线程上修改事件,则需要本地副本。C++/CLI定义了三种方法:
add
remove
raise
,而
raise
方法实现了空检查和本地复制,这与C#一样,要求每个开发人员自己实现

您的事件是实例成员而不是静态成员,因此您应该在raise方法中使用此关键字来限定事件名称的范围(或者根本不限定它的范围)

EventHandler^local=this->ServiceCollectionChanged;
// C++/CLI *only*. This will cause bugs if you do this in C#.
void NativeImplementation::RaiseServiceCollectionChanged(Type^ type, ChangeAction action)
{
    this->ServiceCollectionChanged(this, gcnew ServiceCollectionChangedEventArgs(type, action));
}
EventHandler<ServiceCollectionChangedEventArgs^>^ local = this->ServiceCollectionChanged;