托管事件的C ++ Cli实现

时间:2017-07-10 08:11:21

标签: events c++-cli

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

public interface IManagedInterface
{
   event EventHandler<ServiceCollectionChangedEventArgs> ServiceCollectionChanged;
}

我的cli组件存在header和.cpp文件。在我的标题中,我定义了事件和一个私有方法来提升它。

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

  private:
    void RaiseServiceCollectionChanged(System::Type^ type, ChangeAction action);
};

在我的.cpp文件中,我想实现raise方法,这就是我在努力的方法。

void NativeImplementation::RaiseServiceCollectionChanged(Type^ type, ChangeAction action)
      {
        EventHandler<ServiceCollectionChangedEventArgs^>^ local = NativeImplementation::ServiceCollectionChanged;
        if (local != nullptr) {
          local(this, gcnew ServiceCollectionChangedEventArgs(type, action));
        }
      }
}

我习惯于在引发事件之前进行上述检查,但编译器会抱怨“错误地使用了事件成员”。谁能帮我?我甚至需要用c ++进行这些检查吗?

由于

2 个答案:

答案 0 :(得分:2)

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

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

你显然试图在C ++ / CLI中遵循相同的模式,但这不是必需的。当您访问班级的event成员时,它会为您执行该习惯用法。您需要做的就是将事件称为函数,并且它将正确完成。

// 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));
}

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

答案 1 :(得分:0)

您的活动是实例成员而不是静态成员,因此您应该在raise方法中使用 this 关键字设置事件名称的范围(或者根本不限制范围)。

EventHandler<ServiceCollectionChangedEventArgs^>^ local = this->ServiceCollectionChanged;