使用CIM SDK创建自定义对象的第一步,就是创建一个自定义的模块,也就是创建一个CimModule的派生类。具体步骤为:
1. 基于CimModule派生一个自定义类,并按需实现其中的虚方法。例如:
// C++ 样式 class MyModule : public CimModule { private: static MyModule *m_sInstance; protected: // 当前模块已被加载时执行此回调,通常我们可在此回调中执行一些模块级的初始化工作,例如: 各种自定 // 义对象的注册、各种全局管理器的初始化等等。 virtual void _OnModuleLoaded() override; // 当前DGN文件已被打开且系统已就绪时执行此回调,通常我们可在此回调中执行一些针对特定DGN的初始 // 化工作,例如:导入所需的Schema文件、启动DGN相关的监听器、在DGN文件级或Model级或Element // 级挂入自定义数据块等等。 virtual void _OnDgnFileOpened(DgnFileR dgnFile) override; // 当前DGN文件将要被关闭时执行此回调,通常我们可以在此回调中执行一些与 OnDgnFileOpened() 相反 // 的操作,例如撤销DGN文件相关的监听器以及先前注册的自定义数据块等等。 virtual void _OnDgnFileToBeClosed(DgnFileR dgnFile, bool changingFiles) override; // 当前模块将要被卸载(或者当前系统即将关闭)时执行此回调,通常我们可以在此回调中执行一些全局管理 // 器的撤销工作。 virtual void _OnModuleToBeUnload() override; // 返回此模块的名称,系统将使用返回的名称来标记此模块,以便于后期管理。 virtual WCharCP _GetName() const; MyModule(); public: static MyModuleR Get(); virtual ~MyModule(); // 此模块启动的入口点函数。 static void Startup(); }; // MyModule
/// <summary> /// C# 方式 /// </summary> public class MyModule : CimModule { /// <summary> /// 静态单例设计模式. /// </summary> private static MyModule s_Module = new MyModule(); /// <summary> /// 获取此模块的名称 /// </summary> /// <returns></returns> protected override string _GetName () { return "MyModuleName"; } /// <summary> /// 模块已加载回调. /// </summary> /// <remarks> /// 所有 CimRoot 的派生类都必须在这里完成注册. /// </remarks> protected override void _OnModuleLoaded () { try { // 注册所有自定义类. MyObjectClass1.DoRegister(); MyObjectClass2.DoRegister(); // 完成其他模块级的初始化工作 } catch ( Exception ex ) { } } /// <summary> /// DGN已初始化完毕回调. /// </summary> /// <param name="dgnFile"></param> Protected override void _OnDgnFileOpened (DgnFile dgnFile) { // 导入本模块中所有自定义类需要使用的Schema文件 CimModuleManager.ImportSchema(null, "Bentley_CIM_Bridge", 1, 0, dgnFile); // 执行其他DGN文件相关的初始化工作. } /// <summary> /// 模块初始化入口点函数. /// </summary> /// <remarks> /// </remarks> public static void Startup () { // 先初始化本模块所依赖的模块 CimCoreModule.Startup(); // 然后将此模块注册到全局的模块管理器中 CimModuleManager.Instance.AddModule(s_Module); } }
2. 在全局入口函数中添加对模块入口点函数的调用,这样,当系统加载模块并调用全局入口点时就会引发模块的初始化。具体方法为:
extern "C" DLLEXPORT void MdlMain(int argc, WCharCP argv[]) { // 注册命令 mdlSystem_registerCommandNumbers (commandNumbers); // 加载命令表资源 mdlParse_loadCommandTable (NULL); // 获取当前主DGN文件 DgnFileP masterDgnFile = mdlDgnFileObj_getMasterFile (); if (NULL == masterDgnFile) return; // 执行模块对象的初始化 MyModule::Startup(); // 显式触发DGN文件已打开回调 CimModuleManager::Get().OnDgnFileOpened(*masterDgnFile); }
/// <summary> /// 用于提供顶层入口点的AddIn派生类. /// </summary> [AddIn(MdlTaskID = "MyDotNETAddIn")] public sealed class MyDotNetAddIn: AddIn { /// <summary> /// 使用静态变量引用实例,以阻止GC回收AddIn实例. /// </summary> private static MyDotNetAddIn s_DotNetAddIn = null; /// <summary> /// 构造符. /// </summary> /// <param name="mdlDesc"></param> public MyDotNetAddIn(System.IntPtr mdlDesc) : base(mdlDesc) { s_DotNetAddIn = this; } /// <summary> /// AddIn入口点函数,宿主加载模块后会立即执行此函数. /// </summary> /// <param name="commandLine"></param> /// <returns></returns> protected override int Run(string[] commandLine) { // 执行自定义模块的初始化函数 MyModule.Startup(); return 0; } }