using System.IO; using System.Windows; using Autodesk.Revit.DB; using Autodesk.Revit.DB.ExtensibleStorage; namespace Sai.Toolkit.Revit.Assist; /// /// 可扩展存储工具Schema框架->由字段Field组成,由Schema可以生成、构建Entity实体 /// 层级关系:Entity->(Schema/Field定义)/Field属性-值 /// 元素阵列不会复制扩展数据 /// /// /// /// IList list = new List { "我的v1", "我的v2", "我的v3", "我的v4" }; /// IDictionary dict = new Dictionary /// { /// { "p1", "v1" }, /// { "p2", "v2" }, /// { "p3", "v3" }, /// { "p4", "v4" } /// }; /// var builder = CreateSchemaBuilder(schemaName); /// //添加字段定义 /// builder.AddSimpleField("simple", typeof(string)); /// builder.AddArrayField("errorModels", typeof(string)); /// builder.AddMapField("dict", typeof(string), typeof(string)); /// builder.AddSingleField("simple"); /// builder.AddListField("errorModels"); /// builder.AddDictField("dict"); /// //创建Schema /// var schema = builder.CreateSchema(); /// var entity = e.CreateEntity(schema); /// e.SetFieldValue("simple", "简单"); /// e.SetFieldValue("errorModels", list); /// e.SetFieldValue("dict", dict); /// public static class ExtensibleStorageAssist { private static Entity GetEntity(this Schema schema, Element element) { if (element is null) { return null; } var entity = element.GetEntity(schema); if (entity.Schema is not null) { return entity; } entity = new Entity(schema); return entity; } /// /// 创建字典类型的字段 /// /// key:Boolean, Byte, Int16, Int32, Float, Double, ElementId,GUID, String, XYZ, UV and Entity /// value:Boolean, Byte, Int16, Int32, Float, Double, ElementId,GUID, String, XYZ, UV and Entity /// /// /// 描述 /// public static FieldBuilder AddDictField(this SchemaBuilder schemaBuilder, string fieldName, string description = "") { if (schemaBuilder is null) { throw new ArgumentNullException(nameof(schemaBuilder)); } if (fieldName is null) { throw new ArgumentNullException(nameof(fieldName)); } //if (!typeof(TK).IsPrimitive) // throw new NotSupportedException(nameof(TK)); //if (!typeof(TV).IsPrimitive) // throw new NotSupportedException(nameof(TV)); if (description == string.Empty) { description = fieldName; } var result = schemaBuilder.AddMapField(fieldName, typeof(TK), typeof(TV)); result.SetDocumentation(description); return result; } /// /// 创建集合类型的字段 /// /// Boolean, Byte, Int16, Int32, Float, Double, ElementId,GUID, String, XYZ, UV and Entity /// /// /// 描述 public static FieldBuilder AddListField(this SchemaBuilder schemaBuilder, string fieldName, string description = "") { if (schemaBuilder is null) { throw new ArgumentNullException(nameof(schemaBuilder)); } if (fieldName is null) { throw new ArgumentNullException(nameof(fieldName)); } //if (!typeof(T).IsPrimitive) // throw new NotSupportedException(nameof(T)); var result = schemaBuilder.AddArrayField(fieldName, typeof(T)); if (description == string.Empty) { description = fieldName; } result.SetDocumentation(description); return result; } /// /// 创建简单类型的字段 /// /// Boolean, Byte, Int16, Int32, Float, Double, ElementId,GUID, String, XYZ, UV and Entity /// /// /// 描述 /// public static FieldBuilder AddSingleField(this SchemaBuilder schemaBuilder, string fieldName, string description = "") { if (schemaBuilder is null) { throw new ArgumentNullException(nameof(schemaBuilder)); } if (fieldName is null) { throw new ArgumentNullException(nameof(fieldName)); } //if (!typeof(T).IsPrimitive) // throw new NotSupportedException(nameof(T)); var result = schemaBuilder.AddSimpleField(fieldName, typeof(T)); //result.SetUnitType(unitType); if (description == string.Empty) { description = fieldName; } result.SetDocumentation(description); return result; } /// /// 创建元素扩展数据实体 /// /// /// /// public static Entity CreateEntity(this Element element, Schema schema) { Entity entity = new(schema); element.SetEntity(entity); return entity; } /// /// 创建Schema /// /// /// public static Schema CreateSchema(this SchemaBuilder builder) { return builder?.Finish(); } /// /// 创建参数的表 /// /// /// /// /// public static SchemaBuilder CreateSchemaBuilder(string schemaName, AccessLevel accessLevel = AccessLevel.Public, string description = null) { if (schemaName is null) { throw new ArgumentNullException(nameof(schemaName)); } SchemaBuilder builder = new(Guid.NewGuid()); builder.SetReadAccessLevel(accessLevel); builder.SetWriteAccessLevel(accessLevel); builder.SetSchemaName(schemaName); description ??= schemaName; builder.SetDocumentation(description); #if USE_FORGETYPEID //roleFieldBuilder.SetSpec(SpecTypeId.Custom);//设置字段值的单位,并不是所有类型都需要单位 #else //roleFieldBuilder.SetUnitType(UnitType.UT_Undefined);//设置字段值的单位,并不是所有类型都需要单位 //roleFieldBuilder1.SetUnitType(UnitType.UT_Undefined);//设置字段值的单位,并不是所有类型都需要单位 //roleFieldBuilder2.SetUnitType(UnitType.UT_Undefined);//设置字段值的单位,并不是所有类型都需要单位 #endif return builder; } /// /// 删除实体 /// /// 元素 /// 字段名 public static void DeleteEntityByFieldName(this Element element, string fieldName) { var schema = element.GetSchemaByFieldName(fieldName); if (schema != null) { element.DeleteEntity(schema); } } /// /// 删除实体 /// /// 元素 /// 表名 public static void DeleteEntityBySchemaName(this Element element, string schemaName) { var schema = element.GetSchemaBySchemaName(schemaName); if (schema != null) { element.DeleteEntity(schema); } } /// /// 获取文件级数据存储 /// /// /// /// /// public static void GetDateStorage(Document doc, string schemaName, string fieldName, string fileName) { DataStorage storage = new FilteredElementCollector(doc).OfClass(typeof(DataStorage)).Cast().First(); Schema sch = Schema.ListSchemas().First(o => o.SchemaName == schemaName); Entity ent = storage.GetEntity(sch); byte[] bytes = ent.Get(sch.GetField(fieldName)).ToArray(); using (FileStream fs = new(fileName, FileMode.Create, FileAccess.Write)) { fs.Write(bytes, 0, bytes.Length); } MessageBox.Show("文件提取完毕!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); } /// /// 获取字段参数值 /// /// 元素 /// 字段名 public static T GetFieldValue(this Element element, string fieldName) where T : new() { if (!typeof(T).IsPrimitive) { throw new NotSupportedException(nameof(T)); } T t = new(); try { Schema schema = element.GetSchemaByFieldName(fieldName); Entity entity = element.GetEntity(schema); if (!entity.IsValid()) { return t; } Field f = schema.GetField(fieldName); return entity.Get(f); } catch { return t; } } /// /// 获取元素的所有字段值 /// /// /// /// public static List GetFiledValues(this Element e) { if (!typeof(T).IsPrimitive) { throw new NotSupportedException(nameof(T)); } List storages = new(); //方法一 var schemaGuids = e.GetEntitySchemaGuids(); foreach (var schemaGuid in schemaGuids) { Schema schema = Schema.Lookup(schemaGuid); Entity ent = e.GetEntity(schema); if (!ent.IsValid()) { return storages; } IList fields = schema.ListFields(); foreach (var field in fields) { var f = ent.Get(field); storages.Add(f); } } //if (storages.Count == 0) //{ // //方法二 // //从内存中获取 Schema 列表 // IList schemas = Schema.ListSchemas(); // //从 Schema 中获取 Field 列表 // foreach (var schema in schemas) // { // IList fields = schema.ListFields(); // Entity ent = e.GetEntity(schema); // foreach (var field in fields) // { // var f = ent.Get(field); // storages.Add(f); // } // } //} return storages; } /// /// 通过字段名称获取Schema /// /// /// /// public static Schema GetSchemaByFieldName(this Element elm, string fieldName) { if (elm is null) { throw new ArgumentNullException(nameof(elm)); } if (fieldName is null) { throw new ArgumentNullException(nameof(fieldName)); } var schemaGuids = elm.GetEntitySchemaGuids(); return schemaGuids.Select(Schema.Lookup).FirstOrDefault(f => f.GetField(fieldName) != null); } /// /// 通过Schema名称获取Schema /// /// /// /// public static Schema GetSchemaBySchemaName(this Element elm, string schemaName) { if (elm is null) { throw new ArgumentNullException(nameof(elm)); } if (schemaName is null) { throw new ArgumentNullException(nameof(schemaName)); } var schemaGuids = elm.GetEntitySchemaGuids(); return schemaGuids.Select(Schema.Lookup).FirstOrDefault(f => f.SchemaName == schemaName); } /// /// 从元素中读取schema中存储的值 /// /// 存储数据的元素 /// Existing schema /// The Field name /// schema中要存储的数据类型。该类型必须与schemabuilder中指定的数据类型相匹配。 /// 存储在元素中的数据。如果字段不存在或数据尚未保存,则返回空值 /// /// /// document.ProjectInformation.LoadEntity<string<(schema, "schemaField") /// /// public static T LoadEntity(this Element element, Schema schema, string fieldName) { var field = schema.GetField(fieldName); var entity = schema.GetEntity(element); return entity is null || field is null ? default : entity.Get(field); } /// /// 在元素中存储数据。现有数据将被覆盖 /// /// 存储数据的元素 /// Existing schema /// Type of data /// The Field name /// The type of data to be stored in the schema. The type must match the type of data specified in the SchemaBuilder /// True if entity save succeeded /// /// /// document.ProjectInformation.SaveEntity(schema, "data", "schemaField") /// /// /// public static bool SaveEntity(this Element element, Schema schema, T data, string fieldName) { var field = schema.GetField(fieldName); if (field is null) { return false; } var entity = schema.GetEntity(element); if (entity is null) { return false; } entity.Set(field, data); element.SetEntity(entity); return true; } /// /// 设置文件级别数据存储 /// /// /// public static void SetDateStorage(Document doc, string fileName) { Transaction tran = new(doc, "BIM"); tran.Start(); //项目文档中使用扩展数据,可以使用静态方法创建 DataStorage store = DataStorage.Create(doc); Schema schema; using (SchemaBuilder schemaBuilder = new(new Guid(Guid.NewGuid().ToString("D")))) { schemaBuilder.SetReadAccessLevel(AccessLevel.Public); schemaBuilder.SetWriteAccessLevel(AccessLevel.Public); schemaBuilder.SetSchemaName("LeiFile"); schemaBuilder.SetDocumentation("DataStorageFile"); FieldBuilder arrayField = schemaBuilder.AddArrayField("data", typeof(byte)); arrayField.SetDocumentation("Store file data"); schema = schemaBuilder.Finish(); } byte[] data; using (FileStream stream = new(fileName, FileMode.Open, FileAccess.Read)) { data = new byte[(int)stream.Length]; stream.Read(data, 0, data.Length); stream.Close(); } Entity entity = new(schema); Field field = schema.GetField("data"); entity.Set(field, data); store.SetEntity(entity); MessageBox.Show("文件存储成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); tran.Commit(); } /// /// 设置可扩展参数的值:简单类型、集合、字典(这一步骤涉及对文档的修改,需在事务中进行) /// /// 元素 /// 字段 /// 字段值 public static void SetFieldValue(this Element element, string fieldName, T value) { Schema schema = element.GetSchemaByFieldName(fieldName); var entity = element.GetEntity(schema); Field field = schema.GetField(fieldName); entity.Set(field, value); element.SetEntity(entity); } /// /// 设置可扩展参数的值:简单类型、集合、字典(这一步骤涉及对文档的修改,需在事务中进行) /// /// 元素 /// /// 字段 /// 字段值 public static void SetFieldValue(this Element element, Schema schema, string fieldName, T value) { var entity = element.GetEntity(schema); Field field = schema.GetField(fieldName); entity.Set(field, value); element.SetEntity(entity); } }