Revit API を使用すると、クラスに似た独自のスキーマ データ構造を作成し、そのインスタンスを Revit モデルの任意の要素にアタッチすることができます。スキーマベースのデータは Revit モデルに保存され、より上位レベルの、メタデータによって拡張された、オブジェクト指向のデータ構造となります。スキーマ データは、すべてのユーザに読み取り/書き込みを許可、特定のアプリケーション ベンダーのみに許可、ベンダーの特定のアプリケーションのみに許可するように設定できます。
Revit の要素にデータを保存するには次の手順が必要です。
拡張ストレージを作成するための最初の手順は、スキーマの定義です。スキーマは、オブジェクト指向プログラミング言語のクラスに似ています。新しいスキーマを作成するには、SchemaBuilder クラスのコンストラクタを使用します。SchemaBuilder はスキーマを作成するためのヘルパー クラスです。SchemaBuilder を使用してスキーマを作成した後、Schema クラスを使用してスキーマのプロパティにアクセスします。この段階で、スキーマは編集できなくなります。
SchemaBuilder コンストラクタはスキーマを識別するために使用する GUID を取りますが、スキーマ名も必要となります。スキーマを作成した後、SchemaBuilder.SetSchemaName()を呼び出して、スキーマに分かりやすい識別子を割り当てます。スキーマ名は、エラー メッセージでスキーマを識別するのに便利です。
スキーマに関連付けられているエンティティの読み取りと書き込みのレベルは個別に設定することができます。Public、Vendor、Application のオプションがあります。読み取りまたは書き込みアクセス レベルが Vendor に設定されている場合、スキーマのエンティティにアクセスする可能性のあるサードパーティ ベンダーの VendorId を設定する必要があります。読み取りまたは書き込みアクセス レベルが Application に設定されている場合、スキーマのエンティティにアクセスする可能性のあるアプリケーションまたはアドインの GUID を設定する必要があります。
スキーマを作成した後、フィールドを定義することができます。フィールドはクラスのプロパティに似ています。名前、ドキュメント、値タイプと単位のタイプを持ちます。フィールドは単純タイプ、配列、マップに設定できます。次の単純データ タイプが許可されています。
タイプ |
既定値 |
int |
0 |
short |
0 |
byte |
0 |
double |
0.0 |
float |
0.0 |
bool |
false |
string |
空の文字列("") |
GUID |
Guid.Empty {00000000-0000-0000-0000-000000000000} |
ElementId |
ElementId.InvalidElementId |
Autodesk.Revit.DB.XYZ |
(0.0,0.0,0.0) |
Autodesk.Revit.DB.UV |
(0.0,0.0) |
さらに、フィールドを Autodesk.Revit.DB.ExtensibleStorage.Entity タイプとすることもできます。つまり、別のスキーマのインスタンス(SubSchema や SubEntity と呼ばれる)とすることもできます。このタイプのフィールドの既定値は null スキーマを持つ Entity で、GUID は Guid.Empty となります。
単純フィールドは SchemaBuilder.AddSimpleField()メソッドを使用して作成することができ、フィールドの名前とタイプを指定します。AddSimpleField()は、フィールドを定義するためのヘルパー クラスである FieldBuilder を返します。フィールドのタイプを Entity として指定した場合は、FieldBuilder.SetSubSchemaGUID()を使用して、このフィールドに保存するエンティティのスキーマの GUID を指定します。
含まれる値の名前とタイプを指定して、スキーマに値の配列を持つフィールドを作成するには、SchemaBuilder.AddArrayField()メソッドを使用します。配列フィールドには単純フィールドと同じタイプをすべて指定することができます。
含まれる値の名前、キーのタイプ、値のタイプを指定して、スキーマに編成されたキー値マップを持つフィールドを作成するには、SchemaBuilder.AddMapField()メソッドを使用します。サポートされる値のタイプは単純フィールドのタイプと同じです。サポートされるキーのタイプは、int、short、byte、string、bool、ElementId、GUID に限定されます。
SchemaBuilder を使用してスキーマを完成させると、FieldBuilder を使用したフィールドの編集はできなくなります。この段階で、Schema クラスでは名前でフィールドを取得するメソッドや、スキーマ内に定義されているすべてのフィールドのリストを取得するメソッドを使用できます。
スキーマのすべてのフィールドを定義した後、SchemaBuilder.Finish()が完成したスキーマを返します。そのスキーマを使用すれば、新しいエンティティを作成できます。スキーマの各フィールドに対しては、フィールドと値(そのタイプはフィールド タイプによって異なる)を取る Entity.Set()を使用して値を保存できます。エンティティの適用可能なすべてのフィールドを設定した後、Element.SetEntity()メソッドを使用して要素に割り当てることができます。
後でデータを取得するには、Element.GetEntity()を呼び出して対応するスキーマに渡します。該当するスキーマに基づくエンティティが要素に保存されていない場合は、無効なエンティティが返されます。有効なエンティティが返されたことを確認するには、Entity.IsValid()メソッドを呼び出します。エンティティのフィールド値は、Entity.Get()メソッドを使用することで取得できます。
要素に保存されているエンティティを確認するには、Element.GetEntitySchemaGuids()メソッドを使用します。このメソッドは要素のエンティティのスキーマ GUID を返します。スキーマ GUID を静的メソッド Schema.Lookup()とともに使用すると、対応するスキーマを取得できます。
次は、これらの手順を 1 つにまとめた例です。
コード領域 22-9: 拡張ストレージ |
// Create a data structure, attach it to a wall, populate it with data, and retrieve the data back from the wall void StoreDataInWall(Wall wall, XYZ dataToStore) { Transaction createSchemaAndStoreData = new Transaction(wall.Document, "tCreateAndStore"); createSchemaAndStoreData.Start(); SchemaBuilder schemaBuilder = new SchemaBuilder(new Guid("720080CB-DA99-40DC-9415-E53F280AA1F0")); schemaBuilder.SetReadAccessLevel(AccessLevel.Public); // allow anyone to read the object schemaBuilder.SetWriteAccessLevel(AccessLevel.Vendor); // restrict writing to this vendor only schemaBuilder.SetVendorId("ADSK"); // required because of restricted write-access schemaBuilder.SetSchemaName("WireSpliceLocation"); // 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."); Schema schema = schemaBuilder.Finish(); // register the Schema object Entity entity = new Entity(schema); // create an entity (object) for this schema (class) // 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); wall.SetEntity(entity); // store the entity in the element // get the data back from the wall Entity retrievedEntity = wall.GetEntity(schema); XYZ retrievedData = retrievedEntity.Get<XYZ>(schema.GetField("WireSpliceLocation"), DisplayUnitType.DUT_METERS); createSchemaAndStoreData.Commit(); } |
フィールド、単位、サブエンティティ、説明文字列を追加してスキーマを作成するのは、データを保存する手段だからというだけではありません。これは、他のユーザの潜在的な資料となり、同じスキーマのエンティティを後で作成するとき、より簡単にできるようになります。
スキーマのエンティティは要素ごとに保存されるため、アプリケーションが現在選択している梁のデータのみを必要としている場合、必ずしもドキュメント内のすべての拡張ストレージ データ(すべての梁ファミリ インスタンスのすべてのデータ)を読み込む必要はありません。これにより、よりターゲットを絞ったデータ アクセス コードが可能となり、全体のデータ アクセス パフォーマンスも改善します。