我想在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 ++进行这些检查吗?
由于
答案 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#为每个事件成员定义了两种方法:add
和remove
,在使用+=
和-=
时调用这些方法。上面的习惯用法是必要的,因为没有内置的空检查,如果在空检查和实际触发事件之间的另一个线程上修改了事件,则需要本地副本。 C ++ / CLI定义了三种方法:add
,remove
和raise
,raise
方法实现了空检查和本地复制,与C#一样需要每个开发人员实现自己。
答案 1 :(得分:0)
您的活动是实例成员而不是静态成员,因此您应该在raise方法中使用 this 关键字设置事件名称的范围(或者根本不限制范围)。
EventHandler<ServiceCollectionChangedEventArgs^>^ local = this->ServiceCollectionChanged;