更新参数化单元定义


Mstn中提供的参数化建模工具可以使我们不再像传统建模工具那样创建出来的都是一些固定的模型,这些固定模型的某个尺寸如果发生变化需要更改时需要从头开始重新去画。使用参数化建模工具创建出的参数化模型可以预设一些参数,后期参数值需要修改时,我们只需要在模型的属性对话框中直接修改即可。在参数化建模的基础之上,我们还可以使用新增加的参数化单元功能来重复使用这些参数化模型,参数化单元底层工作原理有点类似于共享单元,在一份新建的dgn文件中如果从某个单元库中获取参数化单元定义去放置参数化单元时,第一次放置时会在当前dgn文件中先创建一个不可见的参数化单元定义元素,然后才会去创建我们看到的参数化单元元素,这个参数化单元元素会引用刚刚创建的参数化单元定义。后续再放置这个参数化单元时,就不会再先创建参数化单元定义元素了,而是直接创建参数化单元元素直接引用第一次放置时创建的定义元素。了解参数化单元底层工作原理后,我们就能理解今天这篇文章关注的参数化单元定义更新的问题了。我们在dgn文件中放置了参数化单元以后,如果单元库中参数化单元定义发生了变化的话,我们的dgn文件中创建的参数化单元定义元素是不会自动更新的,所以不仅先前放置的参数化单元不会看到定义中新增加的变化,就是我们再放置出来的参数化单元也还是老样子,所以这个时候我们就需要去做一个更新当前dgn文件中参数化单元定义元素的操作。Mstn界面上给我们提供了更新的操作工具,我们今天这篇文章给大家介绍一下如果通过编程来实现更新。我们先看代码:

        private static DgnComponentDefinitionModelHandler LocateCellModelHandler(string name)
        {
            var opts = CellLibraryOptions.Include3d | CellLibraryOptions.IncludeAllLibraries | CellLibraryOptions.IncludeParametric;
            var libs = new CellLibraryCollection(opts);
            DgnModel cellModel = null;
            foreach (var lib in libs)
            {
                if (name.Equals(lib.Name))
                {
                    StatusInt status;
                    cellModel = lib.File.LoadRootModelById(out status, lib.File.FindModelIdByName(lib.Name), true, false, true);
                    break;
                }
            }

            var hdlr = null != cellModel ? DgnComponentDefinitionHandler.GetForModel(cellModel) : null;
            return null != hdlr ? hdlr.DefinitionModelHandler : null;
        }
        public static void UpdateCellDef()
        {
            string cellName = "Double Door Cabinet";
            ParametricCellDefinitionElement cellDef = ParametricCellDefinitionElement.FindByName("Double Door Cabinet", Session.Instance.GetActiveDgnFile());
            if (null == cellDef)
                return;
            var hdlr = LocateCellModelHandler(cellName);
            Type type = typeof(UpdateCellVm);
            ConstructorInfo[] conInfoArr = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
            if (0 == conInfoArr.Length)
                return;
            object[] objArr = new object[2] { cellDef,hdlr  };
            object obj = conInfoArr[0].Invoke(objArr);
            MethodInfo oMethod = type.GetMethod("DoUpdate", BindingFlags.Instance | BindingFlags.NonPublic);
            oMethod.Invoke(obj, new Object[] { });
        }

这段代码我们以Mstn安装时自带的一个单元库文件“Double Door Cabinet.dgn”为例来演示,更新参数化单元定义我们主要使用到的对象类型是“UpdateCellVm”,这个类型在程序集“C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\MdlSys\Asneeded\Bentley.ParametricCells.dll”中,我们需要调用其DoUpdate成员函数来完成更新。由于这个函数为非“Public”类型,所以我们只能通过获取其类型信息“Type”的实例来调用这个函数。