Building Coder(Revit 二次开发) - 可扩展存储处理字典
来源:互联网 发布:东三省十大网络神曲 编辑:程序博客网 时间:2024/05/15 00:16
原文链接:Extensible Storage of a Map
我在前面的博文里已经介绍过 Revit 2012 API 中新引入的可扩展存储功能 extensible storage。你还可以在 DevHelp Online 和 Revit 2012 API webcast 找到更多的细节。
最近我更新了网络广播上的例程,下面是最新的主函数代码:
我在前面的博文里已经介绍过 Revit 2012 API 中新引入的可扩展存储功能 extensible storage。你还可以在 DevHelp Online 和 Revit 2012 API webcast 找到更多的细节。
最近我更新了网络广播上的例程,下面是最新的主函数代码:
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ){ UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; try { // pick an element and define the XYZ // data to store at the same time Reference r = uidoc.Selection.PickObject( ObjectType.Face, new WallFilter(), "Please pick a wall at a point on one of its faces" ); Wall wall = doc.get_Element( r.ElementId ) as Wall; XYZ dataToStore = r.GlobalPoint; Transaction t = new Transaction( doc, "Create Extensible Storage Schemata and Store Data" ); t.Start(); // store the data, and also // demonstrate reading it back StoreDataInWall( wall, dataToStore ); t.Commit(); // list all schemas in memory across all documents ListSchemas(); return Result.Succeeded; } catch( Exception ex ) { message = ex.Message; return Result.Failed; }}这个外部命令首先要求用户通过指定点来选择一面墙体。PickObject 方法可以同时返回选中的墙体和选中的点。它使用一个实现了 ISelectionFilter 接口的 WallFilter 对象作为参数,来限制用户只能选择墙体。
class WallFilter : ISelectionFilter{ public bool AllowElement( Element e ) { return e is Wall; } public bool AllowReference( Reference r, XYZ p ) { return true; }}选中的点被封装为一个可扩展存储样式,然后保存到墙体模型中。下面是实现封装的辅助函数:
/// <summary>/// Create an extensible storage schema, /// attach it to a wall, populate it with data, /// and retrieve the data back from the wall./// </summary>void StoreDataInWall( Wall wall, XYZ dataToStore ){ SchemaBuilder schemaBuilder = new SchemaBuilder( new Guid( "720080CB-DA99-40DC-9415-E53F280AA1F0" ) ); // allow anyone to read the object schemaBuilder.SetReadAccessLevel( AccessLevel.Public ); // restrict writing to this vendor only schemaBuilder.SetWriteAccessLevel( AccessLevel.Vendor ); // required because of restricted write-access schemaBuilder.SetVendorId( "ADNP" ); // create a field to store an XYZ FieldBuilder fieldBuilder = schemaBuilder .AddSimpleField( "WireSpliceLocation", typeof( XYZ ) ); fieldBuilder.SetUnitType( UnitType.UT_Length ); fieldBuilder.SetDocumentation( "A stored " + "location value representing a wiring " + "splice in a wall." ); schemaBuilder.SetSchemaName( "WireSpliceLocation" ); // register the schema Schema schema = schemaBuilder.Finish(); // create an entity (object) for this schema (class) Entity entity = new Entity( schema ); // get the field from the schema Field fieldSpliceLocation = schema.GetField( "WireSpliceLocation" ); // set the value for this entity entity.Set<XYZ>( fieldSpliceLocation, dataToStore, DisplayUnitType.DUT_METERS ); // store the entity on the element wall.SetEntity( entity ); // read back the data from the wall Entity retrievedEntity = wall.GetEntity( schema ); XYZ retrievedData = retrievedEntity.Get<XYZ>( schema.GetField( "WireSpliceLocation" ), DisplayUnitType.DUT_METERS );}上面的主函数还调用了另外一个辅助函数 ListSchemas 来显示所有被加载到当前文档中的样式。
/// <summary>/// List all schemas in Revit memory across all documents./// </summary>void ListSchemas(){ IList<Schema> schemas = Schema.ListSchemas(); int n = schemas.Count; Debug.Print( string.Format( "{0} schema{1} defined:", n, PluralSuffix( n ) ) ); foreach( Schema s in schemas ) { IList<Field> fields = s.ListFields(); n = fields.Count; Debug.Print( string.Format( "Schema '{0}' has {1} field{2}:", s.SchemaName, n, PluralSuffix( n ) ) ); foreach( Field f in fields ) { Debug.Print( string.Format( "Field '{0}' has value type {1}" + " and unit type {2}", f.FieldName, f.ValueType, f.UnitType ) ); } }}
利用可扩展存储保存一个字典
在上面的例子里,我们只保存了一个简单的 XYZ 数据。最近我被问及如何保存一个更加复杂的数据,比方说字典。
提问
我想使用以下代码将一个字符串字典保存到文档中:
FieldBuilder.AddMapField( MyMappedField, typeof( string ), typeof( string ) );
但问题是我应该如何调用 Entity.Set<???>(???) 方法呢?类似地问题还有,如何读取和删除字典类型的数据呢?
回答
简单地说,应该使用 IDictionary<> 作为类型参数调用 Entity.Set<>() 方法,即使实际的数据类型是 Dictionary<>。实际上 Revit API 的帮助文档提到了这一点,不过叙述得不太清楚。顺便说一句,SDK 例程 ExtensibleStorageManager 里也有实际的代码。// Note that we use IDictionary<> for // map types and IList<> for array types mySchemaWrapper .AddField<IDictionary<string, string>>( map0Name, UnitType.UT_Undefined, null ); mySchemaWrapper .AddField<IList<bool>>( array0Name, UnitType.UT_Undefined, null );我更新了之前提到的网络广播的例程,最新的主函数如下:
/// <summary>/// Create an extensible storage schema specifying /// a dictionary mapping keys to values, both using /// strings, populate it with data, attach it to the /// given element, and retrieve the data back again./// </summary>void StoreStringMapInElement( Element e ){ SchemaBuilder schemaBuilder = new SchemaBuilder( new Guid( "F1697E22-9338-4A5C-8317-5B6EE088ECB4" ) ); // allow anyone to read or write the object schemaBuilder.SetReadAccessLevel( AccessLevel.Public ); schemaBuilder.SetWriteAccessLevel( AccessLevel.Public ); // create a field to store a string map FieldBuilder fieldBuilder = schemaBuilder.AddMapField( "StringMap", typeof( string ), typeof( string ) ); fieldBuilder.SetDocumentation( "A string map for Tobias." ); schemaBuilder.SetSchemaName( "TobiasStringMap" ); // register the schema Schema schema = schemaBuilder.Finish(); // create an entity (object) for this schema (class) Entity entity = new Entity( schema ); // get the field from the schema Field field = schema.GetField( "StringMap" ); // set the value for this entity IDictionary<string, string> stringMap = new Dictionary<string, string>(); stringMap.Add( "key1", "value1" ); stringMap.Add( "key2", "value2" ); entity.Set<IDictionary<string, string>>( field, stringMap ); // store the entity on the element e.SetEntity( entity ); // read back the data from the wall Entity retrievedEntity = e.GetEntity( schema ); IDictionary<string, string> stringMap2 = retrievedEntity .Get<IDictionary<string, string>>( schema.GetField( "StringMap" ) );}你也可以从这里下载完整的代码 ExtensibleStorage.zip。
- Building Coder(Revit 二次开发) - 可扩展存储处理字典
- Building Coder(Revit 二次开发) - 可扩展存储
- Building Coder(Revit 二次开发) - 失败处理API(上)
- Building Coder(Revit 二次开发) - 失败处理API(下)
- Building Coder(Revit 二次开发) - 对象关系
- Building Coder(Revit 二次开发) - RevitLoopup 更新
- Building Coder(Revit 二次开发) - 拖放API
- Building Coder(Revit 二次开发) - 组合使用 Revit 和 Vault
- Building Coder(Revit 二次开发) - 翻译 Revit Tooltip
- Building Coder(Revit 二次开发) - 元素层级事件(上)
- Building Coder(Revit 二次开发) - 元素层级事件(下)
- Building Coder(Revit 二次开发) - 复制 Legend 组件
- Building Coder(Revit 二次开发) - 参数访问和计划信息
- Building Coder(Revit 二次开发) - 放置族实例
- Building Coder(Revit 二次开发) - 设置标签类型
- Building Coder(Revit 二次开发) - 族元素可见性
- Building Coder(Revit 二次开发) - 改变元素类型
- Building Coder(Revit 二次开发) - 共享类型参数
- [Beginning Visual C++2008 ] 替换数组中最小的数
- 用户js判断
- Windows+Oracle10G10.2.0.1Upgrade to 10.2.0.5
- Spring的配置文件,可以用applicationContext.xml+applicationContext.properties
- Java 泛型学习笔记(二)
- Building Coder(Revit 二次开发) - 可扩展存储处理字典
- 单行本App在iOS平台的尴尬处境
- Hadoop HDFS分布式文件系统设计要点与架构
- Oracle的几个基本概念
- Structure Member Alignment, Padding and Data Packing
- ActiveMQ 2
- Android查看数据库
- Dart 语言惯用语——Dart中特有的代码味道
- ActiveMQ 3