Working with EC Properties using Native and Managed APIs

This blog provides some code snips that demonstrate how to use DgnEC Native and Managed API’s for following:

  1. Perform operations on primitive type EC Properties i.e. set  and get. 
  2. Perform operations on array type EC Property i.e. set, get, insert and remove array element.
  3. Perform operations on struct type EC Property i.e. set and  get. 
  4. Perform operations on struct array type EC Property i.e. set, get, insert and remove struct element.
  5. Perform operations on nested struct array type EC Property i.e. set, get, insert and remove nested struct element.

Sample EC Schema

Following is the EC Schema used to perform different operations onto EC Properties:

<?xml version="1.0" encoding="utf-8"?>
<ECSchema schemaName="PropertyTypes" nameSpacePrefix="pt" version="1.0" description="For testing properties" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0">
    <ECClass typeName="PropertiesClass" isDomainClass="True">
        <ECProperty propertyName="StringProperty" typeName="string" />
        <ECProperty propertyName="IntProperty" typeName="int" />
        <ECProperty propertyName="DoubleProperty" typeName="double" />
        <ECProperty propertyName="BooleanProperty" typeName="boolean" />
        <ECProperty propertyName="LongProperty" typeName="long" />
        <ECProperty propertyName="DateTimeProperty" typeName="dateTime" />
        <ECArrayProperty propertyName="ArrayProperty" typeName="string" minOccurs="1" maxOccurs="unbounded" />
        <ECProperty propertyName="Point2dProperty" typeName="point2d" />
        <ECProperty propertyName="Point3dProperty" typeName="point3d" />
	<ECStructProperty propertyName="StructProperty" typeName="StructType" />
	<ECArrayProperty propertyName="StuctArrayProperty" typeName="StructType" minOccurs="1" maxOccurs="unbounded"/>
	<ECArrayProperty propertyName="ComplicatedStuctArrayProperty" typeName="ClassWithStructArray" minOccurs="1" maxOccurs="unbounded"/>
    </ECClass>
	<!-- Struct class should not be marked as domain class-->
    <ECClass typeName="StructType" isStruct="True" isDomainClass="false">
        <ECProperty propertyName="IntegerProperty" typeName="int" />
        <ECProperty propertyName="StringValueProperty" typeName="string"/>
    </ECClass>
    <ECClass typeName="ClassWithStructArray" isStruct="True" isDomainClass="false">
        <ECProperty propertyName="NestedStringProperty" typeName="string"/>
	<ECArrayProperty propertyName="NestedStructArray" typeName="StructType" minOccurs="1" maxOccurs="unbounded"/>
    </ECClass>
</ECSchema>

API’s to work with primitive properties

Following are the APIs used to set primitive type EC properties and get their values:

  • Native API to work with primitive properties

DgnElementECInstancePtr s_propertiesClassInstance;
//Set primitive type properties using property access string and ECValue object
s_propertiesClassInstance->SetValue(m_intPropertyName, ECValue(3));
ECValue value;
//To get property value, pass ECValue object and property access string
ECObjectsStatus status = s_propertiesClassInstance->GetValue(value, m_intPropertyName);
int intVal = value.GetInteger();
s_propertiesClassInstance->SetValue(m_stringPropertyName, ECValue(L"Manufacturer")); 
status = s_propertiesClassInstance->GetValue(value, m_stringPropertyName);
WCharCP stringVal = value.GetString();
s_propertiesClassInstance->SetValue(m_doublePropertyName, ECValue(2.8));
status = s_propertiesClassInstance->GetValue(value, m_doublePropertyName);
double doubleVal = value.GetDouble();
s_propertiesClassInstance->SetValue(m_booleanPropertyName, ECValue(true));
status = s_propertiesClassInstance->GetValue(value, m_booleanPropertyName);
WCharCP boolVal = value.GetBoolean() ? L"true" : L"false";
s_propertiesClassInstance->SetValue(m_longPropertyName, ECValue(286377383789));
status = s_propertiesClassInstance->GetValue(value, m_longPropertyName);
long long longVal = value.GetLong();
DateTime dateTime(DateTime::Kind::Utc, 2018, 12, 5, 6, 28, 48);
value.SetDateTime(dateTime);
s_propertiesClassInstance->SetValue(m_dateTimePropertyName, value);
status = s_propertiesClassInstance->GetValue(value, m_dateTimePropertyName);
DateTime timeVal = value.GetDateTime();
value.SetPoint2D(DPoint2d::From(12.34, 56.78));
s_propertiesClassInstance->SetValue(m_point2dPropertyName, value);
status = s_propertiesClassInstance->GetValue(value, m_point2dPropertyName);
DPoint2d point2d = value.GetPoint2D(); 
value.SetPoint3D(DPoint3d::From(12.34, 56.78, 45.86));
s_propertiesClassInstance->SetValue(m_point3dPropertyName, value);
status = s_propertiesClassInstance->GetValue(value, m_point3dPropertyName);
DPoint3d point3d = value.GetPoint3D();

  • Managed API to work with primitive properties

IDgnECInstance s_propertiesClassInstance;
//Set property value using property access string
s_propertiesClassInstance["StringProperty"].StringValue = "First string value";
//Get property value using property access string
IECPropertyValue propVal = s_propertiesClassInstance["StringProperty"];
string stringValue = propVal.StringValue;
//Set property value using Set method
s_propertiesClassInstance.SetString("StringProperty", "TestString");
//Get property value using Get method
string temp = s_propertiesClassInstance.GetString("StringProperty");

//We can set and get all other properties using above specified ways
s_propertiesClassInstance["IntProperty"].IntValue = 3;
propVal = s_propertiesClassInstance["IntProperty"];
int intValue = propVal.IntValue;
s_propertiesClassInstance["DoubleProperty"].DoubleValue = 2.8;
propVal = s_propertiesClassInstance["DoubleProperty"];
double doubleValue = propVal.DoubleValue;
s_propertiesClassInstance["BooleanProperty"].NativeValue = true;
propVal = s_propertiesClassInstance["BooleanProperty"];
object boolValue = propVal.NativeValue;
s_propertiesClassInstance["LongProperty"].NativeValue = 286377383789;
propVal = s_propertiesClassInstance["LongProperty"];
object longValue = propVal.NativeValue;
DateTime defaultDateTime = new DateTime(1994, 12, 10, 10, 0, 0);
s_propertiesClassInstance["DateTimeProperty"].NativeValue = defaultDateTime;
propVal = s_propertiesClassInstance["DateTimeProperty"];
string dateTimeValue = propVal.NativeValue.ToString()
DPoint2d point2d = new DPoint2d(2, 5);
s_propertiesClassInstance["Point2dProperty"].NativeValue = point2d;
propVal = s_propertiesClassInstance["Point2dProperty"];
object point2dValue = propVal.NativeValue;
DPoint3d point3d = new DPoint3d(3, 5, 6);
s_propertiesClassInstance["Point3dProperty"].NativeValue = point3d;
propVal = s_propertiesClassInstance["Point3dProperty"];
object point3dValue = propVal.NativeValue;

//Another way to set EC properties and to get it's values
DPoint2d point2d = new DPoint2d(4, 9);
s_propertiesClassInstance.SetValue<DPoint2d>("Point2dProperty", point2d);
DPoint2d point2dvalue = s_propertiesClassInstance.GetValueOrDefault<DPoint2d>("Point2dProperty");

API’s to work with array properties

Following are the APIs used to set array type EC property, get array property value, insert array element  and remove array element:

  • Native API to work with array property

DgnElementECInstancePtr s_propertiesClassInstance;
//To add array elements, pass property access string and count of elements to be added
s_propertiesClassInstance->AddArrayElements(m_arrayPropertyName, count);
//To set value for particular index
s_propertiesClassInstance->SetValue(m_arrayPropertyName, ECValue(L"TestString1"), index);
ECValue value;
//Get all array elements from array property
ECObjectsStatus status = s_propertiesClassInstance->GetValue(value, m_arrayPropertyName);
ArrayInfo arrayInfo = value.GetArrayInfo();
int noOfElement = arrayInfo.GetCount();
for (int i = 0; i < noOfElement; i++)
    { 
    s_propertiesClassInstance->GetValue(value, m_arrayPropertyName, i);
    }
//To remove array element, pass access string and index of element to be removed
ECObjectsStatus status = s_propertiesClassInstance-> RemoveArrayElement(m_arrayPropertyName,1);
//To insert array element, pass access string, starting index at which to inset new element and number of elements to insert
status = s_propertiesClassInstance->InsertArrayElements(m_arrayPropertyName,1,1);

  • Managed API to work with array property

IDgnECInstance s_propertiesClassInstance;
//Add elements to array using property access string
s_propertiesClassInstance["ArrayProperty[0]"].StringValue = "FirstString";
//Get all array elements using property access string
IECPropertyValue propVal = s_propertiesClassInstance["ArrayProperty"];
IECArrayValue stringArrayProp = propVal.ContainedValues as IECArrayValue;
for (int i = 0; i < stringArrayProp.Count; i++)
    {
    MessageCenter.Instance.StatusMessage = stringArrayProp[i].StringValue;
    }
//Get all array elements using GetPropertyValue API
propVal = s_propertiesClassInstance.GetPropertyValue("ArrayProperty");
stringArrayProp = propVal.ContainedValues as IECArrayValue;
for (int i = 0; i < stringArrayProp.Count; i++)
    {
    MessageCenter.Instance.StatusMessage = stringArrayProp[i].StringValue;
    }
//Remove array element from particular location of array
propVal = s_propertiesClassInstance["ArrayProperty"];
stringArrayProp = propVal.ContainedValues as IECArrayValue;
stringArrayProp.RemoveAt(1);//Remove element from specified position
//Insert array element to particular location of array
propVal = s_propertiesClassInstance["ArrayProperty"];
stringArrayProp = propVal.ContainedValues as IECArrayValue;
stringArrayProp.InsertAt(1);//InsertAt create empty space in array for specified position
//Set array property using GetOrCreateArray 
IEnumerable<string> stringArray = new[] { "small","medium","large" };
stringArrayProp = s_propertiesClassInstance.GetOrCreateArray("ArrayProperty");
stringArrayProp.SetStrings(stringArray); //SetStrings takes string array and set it to array property
//Get array elements using GetArray API
stringArrayProp = s_propertiesClassInstance.GetArray("ArrayProperty");
for (int i=0; i< stringArrayProp.Count; i++)
    {
    MessageCenter.Instance.StatusMessage = stringArrayProp[i].StringValue;
    }
//Another way to get array property value using TryGetStringValue
string stringValue;
s_propertiesClassInstance.GetArray("ArrayProperty").TryGetStringValue(out stringValue);

API’s to work with struct properties

Following are the APIs used to set struct type EC property and get their values:

  • Native API to work with struct property

DgnElementECInstancePtr s_propertiesClassInstance;
//Set individual property of struct type class
s_propertiesClassInstance->SetValue(L"StructProperty.IntegerProperty", ECValue(3));
//Get individual property value of struct type class
ECValue value;
ECObjectsStatus status = s_propertiesClassInstance->GetValue(value, L"StructProperty.IntegerProperty");
int intValue = value.GetInteger();

  • Managed API to work with struct property

IDgnECInstance s_propertiesClassInstance;
//Set individual property value of struct type class
s_propertiesClassInstance["StructProperty.IntegerProperty"].IntValue = 2;
//Get individual property value of struct type class
IECPropertyValue propVal = s_propertiesClassInstance["StructProperty.IntegerProperty"];
int intValue = propVal.IntValue;
//Get struct type property value as a single string
propVal = s_propertiesClassInstance["StructProperty"];
MessageCenter.Instance.StatusMessage = propVal.StringValue;

//Set value to struct property using GetOrCreateStruct
IECStructValue structVal = s_propertiesClassInstance.GetOrCreateStruct("StructProperty");
structVal.SetInteger("IntegerProperty", 4);
//Get struct type property value using GetStruct
structVal = s_propertiesClassInstance.GetStruct("StructProperty");
int ? intVal = structVal.GetInteger("IntegerProperty");

//Another way to get value of struct property using TryGetStringValue
string stringValue;
s_propertiesClassInstance.GetStruct("StructProperty").TryGetStringValue(out stringValue);

API’s to work with struct array properties

Following are the APIs used to set struct array type EC property, get struct array property value, insert struct element and remove struct element from struct array

  • Native API to work with struct array property

DgnElementECInstancePtr s_propertiesClassInstance;
//To set struct array property, pass property access string and number of elements to insert into it
s_propertiesClassInstance->AddArrayElements(m_structArrayPropertyName, nElements);
//Get struct type class and create instance of it
ECClassP structClass = s_ecSchema->GetClassP(propertyTypesExample.m_structTypeClass);
IECInstancePtr ecInstance = structClass->GetDefaultStandaloneEnabler()->CreateInstance();
//Set value to created instance properties 
ecInstance->SetValue(m_structIntegerPropertyName, ECValue(1));
//Set instance to ecValue object
ECValue v;
v.SetStruct(ecInstance.get());
//Set ecValue object to particular location in struct array
s_propertiesClassInstance->SetValue(m_structArrayPropertyName, v, index);
//To insert struct element at particular location in struct array, pass property access string, starting index at which to insert new element and number of elements to be inserted
s_propertiesClassInstance->InsertArrayElements(m_structArrayPropertyName, 2, 1);
ecInstance = structClass->GetDefaultStandaloneEnabler()->CreateInstance();
ecInstance->SetValue(m_structIntegerPropertyName, ECValue(3));
v.SetStruct(ecInstance.get());
s_propertiesClassInstance->SetValue(m_structArrayPropertyName, v, 2);

//Get the stuct array property values
ECValue value;
ECObjectsStatus status = s_propertiesClassInstance->GetValue(value, m_structArrayPropertyName);
//Get the array information from ecValue object
int count = (int)(value.GetArrayInfo().GetCount());
for (int i = 0; i < count; i++)
    {
    //Get the value stored at particular index in struct array
    s_propertiesClassInstance->GetValue(value, m_structArrayPropertyName, i);
    //Get struct instance from ecValue object
    IECInstancePtr instance = value.GetStruct();
    instance->GetValue(value, m_structIntegerPropertyName);
    int value = value.GetInteger();
    }

  • Managed API to work with struct array property

IDgnECInstance s_propertiesClassInstance;
//Set struct array property using property access string
s_propertiesClassInstance["StuctArrayProperty[0].IntegerProperty"].IntValue = 1;
s_propertiesClassInstance["StuctArrayProperty[1].IntegerProperty"].IntValue = 2;
//Gets all struct elements from struct array 
IECPropertyValue propVal = s_propertiesClassInstance["StuctArrayProperty"];
IECArrayValue stringArrayProp = propVal.ContainedValues as IECArrayValue;
for (int i = 0; i < stringArrayProp.Count; i++)
    {
    MessageCenter.Instance.StatusMessage = stringArrayProp[i].StringValue;
    }
//Remove struct element from particular location of struct array
propVal = s_propertiesClassInstance["StuctArrayProperty"];
stringArrayProp = propVal.ContainedValues as IECArrayValue;
stringArrayProp.RemoveAt(1);
//Insert struct element at particular location of struct array
propVal = s_propertiesClassInstance["StuctArrayProperty"];
stringArrayProp = propVal.ContainedValues as IECArrayValue;
stringArrayProp.InsertAt(1);
s_propertiesClassInstance.SetInteger("StuctArrayProperty[1].IntegerProperty", 2);

//Set struct array property using GetOrCreateStructArray 
IECStructArrayValue structArrayValue = s_propertiesClassInstance.GetOrCreateStructArray("StuctArrayProperty");
IECStructValue[] structValues = structArrayValue.SetStructs(2).ToArray();
structValues[0].SetInteger("IntegerProperty", 1);
structValues[1].SetInteger("IntegerProperty", 2);

//Get struct array property value using GetStructArray
structArrayValue = s_propertiesClassInstance.GetStructArray("StuctArrayProperty");
structValues = structArrayValue.GetStructs().ToArray();
//To get every struct element in struct array as a single string
for (int i=0; i<structValues.Length; i++)
    {
    structValues[i].StringValue;
    }
//To get struct array element’s individual property values
for (int i = 0; i < structValues.Length; i++)
    {
    int? intVal = structValues[i].GetInteger("IntegerProperty");
    string stringVal = structValues[i].GetString("StringValueProperty");
    }

API’s to work with nested struct array properties

Following are the APIs used to set nested struct array type EC property, get nested struct array property value, insert struct element and remove struct element from nested struct array

  • Native API to work with nested struct array property

DgnElementECInstancePtr s_propertiesClassInstance;
//To set nested struct array property, pass property access string and number of struct elements to insert into it
s_propertiesClassInstance->AddArrayElements(m_complicatedStructArrayPropertyName, nElements);
//Get a class having struct type array and create instance of it
ECClassP classWithStructArray = s_ecSchema->GetClassP(propertyTypesExample.m_classWithStructArray);
IECInstancePtr classWithStructArrayInstance = classWithStructArray-> GetDefaultStandaloneEnabler()->CreateInstance();
//Set value to struct array type property of created instance
classWithStructArrayInstance->AddArrayElements(m_nestedStructArrayPropertyName, nElements);
ECClassP structTypeClass = s_ecSchema->GetClassP(propertyTypesExample.m_structTypeClass);
IECInstancePtr structTypeClassInstance = structTypeClass->GetDefaultStandaloneEnabler()-> CreateInstance();
structTypeClassInstance->SetValue(m_structIntegerPropertyName, ECValue(1));
ECValue value;
value.SetStruct(structTypeClassInstance.get());
classWithStructArrayInstance->SetValue(m_nestedStructArrayPropertyName, value, index);//index specifies particular location at which to insert element
//Set instance of class having struct array to nested struct array property
ECValue structVal;
structVal.SetStruct(classWithStructArrayInstance.get());
s_propertiesClassInstance->SetValue(m_complicatedStructArrayPropertyName, structVal, indexOfComplicatedStructProperty);//indexOfComplicatedStructProperty specifies particular location at which to insert element

//Get nested struct array property values
ECObjectsStatus status = s_propertiesClassInstance->GetValue(value, m_complicatedStructArrayPropertyName);
int count = (int)(value.GetArrayInfo().GetCount());
//Loop till number of elements in nested struct array property
for (int i = 0; i < count; i++)
    {
    s_propertiesClassInstance->GetValue(value, m_complicatedStructArrayPropertyName, i);
    IECInstancePtr instance = value.GetStruct();
    instance->GetValue(value, m_nestedStructArrayPropertyName);
    //Loop till number of nested struct array elements
    int countNested = (int)(value.GetArrayInfo().GetCount());
    for (int j = 0; j < countNested; j++)
        {
        instance->GetValue(value, m_nestedStructArrayPropertyName, j);
        IECInstancePtr structInstance = value.GetStruct();
        structInstance->GetValue(value, m_structIntegerPropertyName);
        int value = value.GetInteger();
        }
    }

  • Managed API to work with nested struct array property

IDgnECInstance s_propertiesClassInstance;
//Set nested struct array property using property access string
s_propertiesClassInstance["ComplicatedStuctArrayProperty[0].NestedStructArray[0].IntegerProperty"].IntValue = 1;
//Gets all elements from nested struct array property
IECPropertyValue propVal = s_propertiesClassInstance["ComplicatedStuctArrayProperty"];
IECArrayValue stringArrayProp = propVal.ContainedValues as IECArrayValue;
for (int i = 0; i < stringArrayProp.Count; i++)
    {
    MessageCenter.Instance.StatusMessage = stringArrayProp[i].StringValue;
    }
//Remove element from particular location of nested struct array
propVal = s_propertiesClassInstance["ComplicatedStuctArrayProperty"];
stringArrayProp = propVal.ContainedValues as IECArrayValue;
stringArrayProp.RemoveAt(1);
//Insert element at particular location of nested struct array
propVal = s_propertiesClassInstance["ComplicatedStuctArrayProperty"];
stringArrayProp = propVal.ContainedValues as IECArrayValue;
stringArrayProp.InsertAt(1);

//Set value to nested struct array property using GetOrCreateStructArray
IECStructArrayValue structArrayValue = s_propertiesClassInstance.GetOrCreateStructArray("ComplicatedStuctArrayProperty");
IECStructValue[] structValues = structArrayValue.SetStructs(2).ToArray();//SetStructs(2) specifies number of elements to be added
IECStructArrayValue nestedStructArrayValue = structValues[0].GetOrCreateStructArray("NestedStructArray");
IECStructValue[] nestedStructValue = nestedStructArrayValue.SetStructs(2).ToArray();
nestedStructValue[0].SetInteger("IntegerProperty",1);
nestedStructValue[0].SetString("StringValueProperty", "FirstString");

//Get value from nested struct array property using GetStructArray
structArrayValue = s_propertiesClassInstance.GetStructArray("ComplicatedStuctArrayProperty");
structValues = structArrayValue.GetStructs().ToArray();
for (int i = 0; i < structValues.Length; i++)
    {
    //To get every struct element in nested struct array as a single string
    MessageCenter.Instance.StatusMessage = structValues[i].StringValue;
    }
for (int i = 0; i < structValues.Length; i++)
    {
    //To get struct array element’s individual property values
    nestedStructArrayValue = structValues[i].GetStructArray("NestedStructArray");
    nestedStructValue = nestedStructArrayValue.GetStructs().ToArray();
    for (int j = 0; j < nestedStructValue.Length; j++)
        {
        int? nestedInt = nestedStructValue[j].GetInteger("IntegerProperty");
        string nestedString = nestedStructValue[j].GetString("StringValueProperty");
        }
    }