使用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;
}
}