在CIM对象的宿主系统——基于Microstation的系统中,每时每刻都发生着各种各样的事件。如果我们能准确的知道许多特定事件的发生时机或者在特定事件发生时我们能得到通知,那么我们就有机会充分利用这些事件以设计一些能与系统紧密结合并协调运行的逻辑单元,从而实现以宿主系统为事件源的事件驱动型产品。比如,我们设计的某些逻辑可能需要在系统当前事务结束后且在图形系统开始全面刷新前被执行,我们需要能准确把握当前激活Model切换前后的时机,我们需要知道何时有Element添加到Model中了,等等。在以上这些场景下,我们就可以使用CIM系统提供的事件管理器CimEventManager来监听并响应系统级别的事件了。
CimEventManager是个全局单例类,它会在CIM内核启动时自动并将自己设置为一个系统范围内的事件源。任何需要监听特定事件的构造,只需从CimEventManager监听即可。在实际使用时,由于CIM同时支持C++和C#两种接口方式,而这两种方式的使用不尽相同,具体如下:
CimEventManager::Get().DropListener(pMyListener);
delete pMyListener;
pMyListener = nullptr;
1. 在期望能监听事件的类中,实现一个具备如下原型的方法:
public void OnEventCallback (object sender, CimEventManager.OnElementPropertyArgs);
2. 在使用监听器之前,将其挂接到事件源上,例如:
CimEventManager.OnElementPropertyChanged += new EventHandler<CimEventManager.OnElementPropertyArgs>(OnEventCallback);
3. 不再需要监听器时,将其从事件源上断开,例如:
CimEventManager.OnElementPropertyChanged -= new EventHandler<CimEventManager.OnElementPropertyArgs>(OnEventCallback);
目前,CimEventManager支持如下类型的事件:
OnElementAdded: 一个Element已添加到特定Model中;
OnElementDeleted: 一个Element已从特定Model中删除;
OnElementPropertyChanged: 附加在特定Element上,特EC实例中特定EC属性的值已从一个值改变为另一个值;
OnElementXAttributeAdded: 一个新的XAttribute已添加到了指定的Element上;
OnElementXAttributeToBeDeleted: 指定Element上指定的XAttribute将要被删除;
OnElementXAttributeModified: 指定Element上指定的XAttribute已被修改;
OnElementXAttributeReplaced: 指定Element上指定XAttribute中所包含的数据已被替换;
OnCurrentTransactionToBeClosed: 当前事务即将关闭,所有修改即将被提交(或称即将生效);
OnDisplayToBeUpdated: 当前事务已关闭,图形系统的更新即将开始;
OnDisplayUpdated: 当前事务已关闭,图形系统的更新也已完成,新的事务即将启动;
OnModelToBeDeleted: 指定的Model即将被从DGN文件中删除;
OnModelAdded: 指定的Model已添加到当前DGN文件中;
OnModelPropertyToBeModified: 指定Model的信息块将要被修改;
OnModelPropertyModified: 指定Model的信息块已被修改;
OnDgnFileOpened: 指定的DGN文件已加载且初始化已完成;
OnDgnFileToBeClosed: 指定的DGN文件即将关闭;
OnModelRefPreActivate: 指定的附件(Attachment)将要激活;
OnModelRefToBeActivate: 当前Model将要从一个Model切换为另一个Model;
OnModelRefActivated: 当前Model已从一个Model切换为另一个Model;
OnEventProperty: 一个扩展类型为CimEventItem的自定义EC属性需要通过此事件响应来完成编辑;
由于事件监听器的运行,是通过监听事件管理器中的事件来驱动的。所以,在设计事件监听器时应遵循以下原则进行:
每个事件的响应不依赖于其他事件的触发顺序;
每个事件的处理不依赖于此事件的历史处理状态(即无状态处理);
每个事件在响应时应将事件参数视为只读的;
每个事件的响应代码应尽可能快的返回;
不再需要事件监听器时应及时将其撤销注册并销毁;