Revit API 提供了一整套存储用户自定义数据的方法。对于成熟的CAD/BIM软件,在提供二次开发能力的时候,都会考虑提供让用户存储自定义数据的方法。
这个例子针对的内容和 Revit API 开发 (10): ExtensibleStorage 外部存储 相同。
这个例子的核心是用 ExtensibleStorage 创建一个简单或复杂的用户自定义数据。如图所示,这两个按钮调用的是同一个方法 CreateSetSave
,而这个方法调用的主逻辑在 StorageCommand.CreateSetAndExport
。针对简单的 case,增加数据的逻辑在:SimpleSchemaAndData
;针对复杂的 case,增加数据的逻辑在:ComplexSchemaAndData
。
在这个例子里面,对 Revit API 做了一个包装,SchemaWrapperTools.SchemaWrapper
。
SchemaWrapper
可以嵌套。这个在后面的例子里会展示。
注意 Schema 的嵌套。
//创建一个 sub schema
SchemaWrapperTools.SchemaWrapper mySubSchemaWrapper0 = SchemaWrapperTools.SchemaWrapper.NewSchema(subEntityGuid0, readAccess, writeAccess, vendorId, applicationId, entity0Name, "A sub entity");
// 为这个 sub schema 添加数据 field
mySubSchemaWrapper0.AddField<int>("subInt0", new ForgeTypeId(), null);
// SchemaWrapper 会调用 Revit API 真正创建 Revit 对应的 Schema
mySubSchemaWrapper0.FinishSchema();
// 将这个 sub schema 作为一个 entity 加到上层的 schema
mySchemaWrapper.AddField<Entity>(entity0Name, new ForgeTypeId(), mySubSchemaWrapper0);
// 创建一个实例,并设定schema 的对应数值
Entity subEnt0 = new Entity(mySubSchemaWrapper0.GetSchema());
subEnt0.Set<int>(mySubSchemaWrapper0.GetSchema().GetField("subInt0"), 11);
Field fieldEntity0 = mySchemaWrapper.GetSchema().GetField(entity0Name);
storageElementEntityWrite.Set(fieldEntity0, subEnt0);
// 创建一个 sub schema
SchemaWrapperTools.SchemaWrapper mySubSchemaWrapper1_Map = SchemaWrapperTools.SchemaWrapper.NewSchema(subEntityGuid_Map1, readAccess, writeAccess, vendorId, applicationId, map1Name, "A map of int to Entity");
mySubSchemaWrapper1_Map.AddField<int>("subInt1", new ForgeTypeId(), null);
mySubSchemaWrapper1_Map.FinishSchema();
//增加一个新的数据 field,这个 field 的类型是 IDictionary,而这个 entity 是 mySubSchemaWrapper1_Map
mySchemaWrapper.AddField<IDictionary<int, Entity>>(map1Name, new ForgeTypeId(), mySubSchemaWrapper1_Map);
// 查询获取上面创建的 field
Field fieldMap1 = mySchemaWrapper.GetSchema().GetField(map1Name);
// 创建和填充数据
Entity subEnt1 = new Entity(mySubSchemaWrapper1_Map.GetSchema());
subEnt1.Set<int>(mySubSchemaWrapper1_Map.GetSchema().GetField("subInt1"), 22);
IDictionary<int, Entity> myMap1 = new Dictionary<int, Entity>();
myMap1.Add(5, subEnt1);
storageElementEntityWrite.Set(fieldMap1, myMap1);
// 创建一个 sub schema
SchemaWrapperTools.SchemaWrapper mySubSchemaWrapper2_Array = SchemaWrapperTools.SchemaWrapper.NewSchema(subEntityGuid_Array2, readAccess, writeAccess, vendorId, applicationId, array1Name, "An array of Entities");
mySubSchemaWrapper2_Array.AddField<int>("subInt2", new ForgeTypeId(), null);
mySubSchemaWrapper2_Array.FinishSchema();
mySchemaWrapper.AddField<IList<Entity>>(array1Name, new ForgeTypeId(), mySubSchemaWrapper2_Array);
// 填充数据
Field fieldArray1 = mySchemaWrapper.GetSchema().GetField(array1Name);
Entity subEnt2 = new Entity(mySubSchemaWrapper2_Array.GetSchema());
subEnt2.Set<int>(mySubSchemaWrapper2_Array.GetSchema().GetField("subInt2"), 33);
IList<Entity> myEntArrayList1 = new List<Entity>();
myEntArrayList1.Add(subEnt2);
myEntArrayList1.Add(subEnt2);
storageElementEntityWrite.Set(fieldArray1, myEntArrayList1);
这个例子还介绍了如何把 Schema 转存为了 xml 文件,以及如何从 xml 反序列回来。整体内容详尽,是一个好的插件例子。不过代码质量也是马马虎虎,例如entity2Name_Array
有些多余。