ECFramework的发展
对于工程信息数据来讲主要分为几何信息和工程信息两大内容,在Bentley的三维平台中已经包含多种的几何引擎提供了曲面,网格和实体三种类型的三维几何数据,而对于工程信息的数据处理Bentley也支持了多种的方式来存储和管理工程数据,最初Bentley采用了link的方式让几何元素和数据关联,但是这种方式在使用的过程中很容易因为非技术原因导致数据与几何元素的对应关系不匹配。后来Bentley通过改进DGN格式引进了xattribuic的方式在DGN文件中开辟一个新的空间存储非几何数据,但是在由于没有统一数据存储的方式和格式,导致不同的专业软件之间无法互相交流,也不符合工程数据的发展趋势。最后,Bentley经过大量的摸索和借鉴形成了一套系统的数据解决方案系统ECFramework (Engineering Content Framework ),通过这套方案Bentley真正实现各个专业软件之间的数据无损流动和交互。
EC框架概念介绍
ECFramework (Engineering Content Framework )不同于应用程序框架,它是一个“解决方案框架”。作为一个解决方案框架,它由库、应用程序和技术组成,用于提供互操作性的解决方案和功能,以及用于处理一般的工程内容(Engineering Content)。ECFramework的设计使得它可以被分段使用,例如,您不必重写整个应用程序来使用它,但是您可以使用它的独立部分。
整个ECFramework包含以下几个方面:
•ECObjects 和ECXML: 用来定义工程内容 (for representing EngineeringContent);
•ECServices: 是一套为多种数据来源的工程环境提供的一套统一的服务;
•ECControls:EngineeringContentBrowser , PropertyPane等控件 ;
•ECClassEditor:外部编辑ECSchema的编辑器 ;
Bentley为您提供了一套丰富的工程应用程序,这些应用程序能够很好地协同工作,并使我们的客户能够解决超出任何单一应用程序范围的问题。ECFramework有助于这些不同的软件之间能够更好的协同和交换数据。
使用EC前,我们的架构是这样的:
使用EC后我们的架构是这样的:
通过上图我们可以发现,在ECFramework的技术支撑下,单个应用程序的价值能在整个解决方案中得到了提升,这也是我们国内经常讲到的统一数据的价值体现。无论是从商业上还是还是技术上,通过ECFramework我们能够做到更多的事情。但ECFramework到底是什么,我们是怎么处理的?让我们从头开始,从ECObjects开始。
ECObjects 概念介绍
在介绍ECObjects之前,我们要知道什么是EC,它的英文全称是Engineering Content,中文的意思是工程内容,所以EC + Objects就是指工程内容对象,这样解释还是有些抽象,我们可以从下面几个方面来理解:
从语言的角度来说:它就相当于一个不同语言的通用语,我们使用这个通用语来描述和定义工程中的数据和元数据。
从编程的角度来说:它就像是.NET框架中提供的可以互相操作的数据标准和元数据。
从面向对象的角度来说:它能够通过OO(Object Oriented)的方式来表达你的数据。
从数据库的角度来说:它就相当于一个的数据库系统里的表格和表格里的数据行,同时提供定义,修改,查询和更新的工程数据的一些列操作。
ECSchema
是描述数据(即元数据)的数据。ECSchema提供了一种表达EC数据的结构、上下文,以及在某种程度上允许对这些数据定义一些方法扩展编程方式、显示行为、分析甚至操作。关键的是,ECSchema在各个方面都是平台独立的。ECSchema的存在有助于实现复杂的互操作性场景。作为一个标准,它将多对多的互操作性情形简化为一对多的情形。作为一个抽象规范,它允许针对特定平台定制API。
下面的示例演示了一个ECSchema:
<?xml version="1.0" encoding="utf-8"?><ECSchema schemaName="AdventureWorks" nameSpacePrefix="AW" version="1.0" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0"><ECSchemaReference name="Bentley_Standard_CustomAttributes" version="01.00" prefix="dmd" /><ECClass typeName="Addresses" isDomainClass="True"><ECCustomAttributes><DictionaryCustomAttributes xmlns="Bentley_Standard_CustomAttributes.01.00"><IsClassDictionary>False</IsClassDictionary></DictionaryCustomAttributes></ECCustomAttributes><ECProperty propertyName="City" typeName="string" /><ECProperty propertyName="PostalCode" typeName="string" /><ECProperty propertyName="StateProvince" typeName="string" /></ECClass><ECClass typeName="CurrencyRate" isDomainClass="True"><ECProperty propertyName="Name" typeName="string" /><ECProperty propertyName="Code" typeName="string" /><ECProperty propertyName="RateDate" typeName="string" /><ECProperty propertyName="AverageRate" typeName="string" /></ECClass><ECClass typeName="ArgentinePesoRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass><ECProperty propertyName="EndOfDayRate" typeName="string" /></ECClass><ECClass typeName="AustralianDollarRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass><ECClass typeName="Bolivar" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass><ECClass typeName="BrazilianRealRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass><ECClass typeName="Employees" isDomainClass="True"><ECProperty propertyName="LastName" typeName="string" /><ECProperty propertyName="FirstName" typeName="string" /><ECProperty propertyName="Gender" typeName="string" /></ECClass><ECClass typeName="Buyer" isDomainClass="True"><BaseClass>Employees</BaseClass></ECClass><ECClass typeName="CanadianDollarRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass><ECClass typeName="CustomerAddresses" isDomainClass="True"><BaseClass>Addresses</BaseClass><ECProperty propertyName="City" typeName="string" /><ECProperty propertyName="PostalCode" typeName="string" /><ECProperty propertyName="StateProvince" typeName="string" /></ECClass><ECClass typeName="Customers" isDomainClass="True"><ECProperty propertyName="AccountNumber" typeName="string" /></ECClass><ECRelationshipClass typeName="CustomersHaveAddresses" isDomainClass="True" strength="referencing" strengthDirection="forward"><Source cardinality="(0,N)" roleLabel="Customers" polymorphic="True"><Class class="Customers" /></Source><Target cardinality="(0,N)" roleLabel="Addresses" polymorphic="True"><Class class="Addresses" /></Target></ECRelationshipClass><ECClass typeName="EuropeanCurrencyRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass><ECClass typeName="DeutscheMarkRate" isDomainClass="True"><BaseClass>EuropeanCurrencyRate</BaseClass></ECClass><ECRelationshipClass typeName="EmployeeHasManager" isDomainClass="True" strength="referencing" strengthDirection="forward"><Source cardinality="(0,N)" roleLabel="Employee" polymorphic="True"><Class class="Employees" /></Source><Target cardinality="(1,1)" roleLabel="Manager" polymorphic="True"><Class class="Employees" /></Target></ECRelationshipClass><ECClass typeName="EURORate" isDomainClass="True"><BaseClass>EuropeanCurrencyRate</BaseClass></ECClass><ECClass typeName="FrenchFrancRate" isDomainClass="True"><BaseClass>EuropeanCurrencyRate</BaseClass></ECClass><ECClass typeName="JobCandidate" isDomainClass="True"><BaseClass>Employees</BaseClass><ECProperty propertyName="ModifiedDate" typeName="dateTime" /></ECClass><ECClass typeName="Location" isDomainClass="True"><ECProperty propertyName="Name" typeName="string" /><ECProperty propertyName="CostRate" typeName="string" /><ECProperty propertyName="Availability" typeName="double" /></ECClass><ECClass typeName="MexicanPesoRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass><ECProperty propertyName="EndOfDayRate" typeName="string" /></ECClass><ECClass typeName="Product" isDomainClass="True"><ECProperty propertyName="Price" typeName="string" /><ECProperty propertyName="Size" typeName="string" /><ECProperty propertyName="Weight" typeName="string" /></ECClass><ECClass typeName="Vendor" isDomainClass="True"><ECProperty propertyName="CreditRating" typeName="string" /><ECProperty propertyName="ActiveFlag" typeName="string" /><ECProperty propertyName="URL" typeName="string" /></ECClass><ECRelationshipClass typeName="ProductVendor" isDomainClass="True" strength="referencing" strengthDirection="forward"><ECProperty propertyName="AverageLeadTime" typeName="string" /><ECProperty propertyName="StandardPrice" typeName="string" /><ECProperty propertyName="AverageOrderQuantity" typeName="string" /><Source cardinality="(0,N)" roleLabel="ProductVendor" polymorphic="True"><Class class="Vendor" /></Source><Target cardinality="(0,N)" roleLabel="ProductVendor (reversed)" polymorphic="True"><Class class="Product" /></Target></ECRelationshipClass><ECClass typeName="SalesOrderDetails" isDomainClass="True"><ECProperty propertyName="Quantity" typeName="int" /><ECProperty propertyName="UnitPrice" typeName="double" /><ECProperty propertyName="ProductName" typeName="string" /></ECClass><ECClass typeName="SalesOrders" isDomainClass="True"><ECProperty propertyName="PurchaseOrderNumber" typeName="string" /><ECProperty propertyName="TotalDue" typeName="string" /></ECClass><ECRelationshipClass typeName="SalesOrdersHaveDetails" isDomainClass="True" strength="referencing" strengthDirection="forward"><Source cardinality="(1,1)" roleLabel="SalesOrders" polymorphic="True"><Class class="SalesOrders" /></Source><Target cardinality="(0,N)" roleLabel="SalesOrderDetails" polymorphic="True"><Class class="SalesOrderDetails" /></Target></ECRelationshipClass><ECClass typeName="SalesPeople" isDomainClass="True"><BaseClass>Employees</BaseClass><ECProperty propertyName="SalesQuota" typeName="string" /></ECClass><ECRelationshipClass typeName="SalesPeopleHaveCustomerAddressList" isDomainClass="True" strength="referencing" strengthDirection="forward"><Source cardinality="(0,N)" roleLabel="SalesPeople" polymorphic="True"><Class class="SalesPeople" /></Source><Target cardinality="(0,N)" roleLabel="CustomerAddresses" polymorphic="True"><Class class="CustomerAddresses" /></Target></ECRelationshipClass><ECRelationshipClass typeName="SalesPeopleHaveOrders" isDomainClass="True" strength="referencing" strengthDirection="forward"><Source cardinality="(1,1)" roleLabel="SalesPerson" polymorphic="True"><Class class="SalesPeople" /></Source><Target cardinality="(0,N)" roleLabel="Orders" polymorphic="True"><Class class="SalesOrders" /></Target></ECRelationshipClass><ECClass typeName="SaudiRiyalRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass><ECClass typeName="StoreCustomer_GUIDID" isDomainClass="True"><ECProperty propertyName="AccountNumber" typeName="string" /><ECProperty propertyName="CustomerName" typeName="string" /></ECClass><ECClass typeName="UnitedKingdomPoundRate" isDomainClass="True"><BaseClass>EuropeanCurrencyRate</BaseClass></ECClass><ECClass typeName="WorkOrder" isDomainClass="True"><ECProperty propertyName="EndDate" typeName="dateTime" /><ECProperty propertyName="StartDate" typeName="dateTime" /><ECProperty propertyName="OrderQuantity" typeName="string" /></ECClass><ECRelationshipClass typeName="WorkOrderLocation" isDomainClass="True" strength="referencing" strengthDirection="forward"><ECProperty propertyName="PlannedCost" typeName="string" /><ECProperty propertyName="ActualCost" typeName="string" /><Source cardinality="(0,N)" roleLabel="WorkOrder" polymorphic="True"><Class class="WorkOrder" /></Source><Target cardinality="(0,N)" roleLabel="Location" polymorphic="True"><Class class="Location" /></Target></ECRelationshipClass><ECClass typeName="YenRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass><ECClass typeName="YuanRate" isDomainClass="True"><BaseClass>CurrencyRate</BaseClass></ECClass></ECSchema>
ECClass
定义工程对象的结构,包括有关工程对象类的任何所需元数据。每个ECInstance都有一个相关的ECClass,可以在运行时获得,这样软件就可以通过编程的方式来查找数据的结构和含义。Ecclass存在于ECSchema的上下文中,通常包含ECProperties。
ECClasses支持定义自定义数据类型,通常用于定义复杂业务对象(称为结构)的子部分。ECClasses支持继承和补充。
ECClass可以自定义元数据的属性修饰,该属性为对象提供附加含义。自定义属性的结构本身是使用一个或多个ECClasses定义的。
ECClasses也提供关系(通过ecrelationshipclases定义)引用,关系定义业务对象类之间关系的结构。
下面的示例显示了使用ECXML定义Wheel对象结构的ECClass的部分内容:
<ECClass typeName="Wheel" isStruct="True" isDomainClass="True"><ECProperty propertyName="WheelGeometry" typeName="Bentley.Geometry.Common.ICircularDisk" /><ECProperty propertyName="Diameter" typeName="double"/><ECProperty propertyName="InnerDiameter" typeName="double"/><ECProperty propertyName="Width" typeName="double"/><ECProperty propertyName="DistanceTraveled" typeName="double"/><ECProperty propertyName="Weight" typeName="double" /><ECProperty propertyName="TirePressure" typeName="double"/><ECStructProperty propertyName="WheelHub" typeName="Hub" /><ECProperty propertyName="SpokeDiameter" typeName="int"/><ECProperty propertyName="SpokeLength" typeName="double"/><!--Unitized array of Doubles--><ECArrayProperty propertyName="SpokeTightness" typeName="double" /></ECClass>
ECInstance
表示单个工程数据对象。对象的结构必须由ECClass定义。假如ECClass被视为数据库中的表,则ECInstance将是该表中的一行。
ECInstances不必真正包含数据,但每个ECInstance都必须有一个ECInstanceID。
下面的示例显示使用ECXML的XML形式表示了一个ECClass “Company” ,拥有单个ECProperty “Name” 的 ECPropertyValue “Bentley”:
<?xml version="1.0" encoding="utf-8" ?><SingleECInstance xmlns="http://www.bentley.com/schemas/Bentley.ECObjects"><Company instanceID="bentley" xmlns="Staff.01.00"><Name>Bentley</Name></Company></SingleECInstance>
注意:
ECInstance有多种用途。它可以是ECCustomAttributes的内容,组成ChangeSets,以及基于EC的应用程序中传递的可互操作对象。
除了保存ECPropertyvalue和实例id之外,ECInstance还保存ECRelationshipInstances,它们本身就是一种特殊的ECInstance类型。这些定义了一个具体的关系从一个特定的实例到另一个。
此外,ECInstance有多种托管和非托管实现.
ECProperty
一个ECProperty是单个数据值的类型和含义的定义,每个EC数据都有相关的ECProperty,这些ECProperty可以在运行时获取,这样我们的软件就可以识别出数据的类型和含义。ECProperty位于ECClass的上下文中,也就是通过ECClass可以获取相关的ECProperty。
ECProperty可以用自定义属性的元数据修饰,该元数据为对象提供附加含义。ECProperty的数据类型可以是内置的基本数据类型,也可以是ECClass定义的自定义数据类型。
下面的示例显示了使用ECXML形式定义Wheel对象结构的ECClass:
<?xml version="1.0" encoding="utf-8" ?><ECClass typeName="Wheel" isStruct="True" isDomainClass="True"><ECProperty propertyName="WheelGeometry" typeName="Bentley.Geometry.Common.ICircularDisk" … /><ECProperty propertyName="Diameter" typeName="double" … /><ECProperty propertyName="InnerDiameter" typeName="double" … /><ECProperty propertyName="Width" typeName="double" … /><ECProperty propertyName="DistanceTraveled" typeName="double" … /><ECProperty propertyName="Weight" typeName="double" … /><ECProperty propertyName="TirePressure" typeName="double" … /><ECStructProperty propertyName="WheelHub" typeName="Hub" /><ECProperty propertyName="SpokeDiameter" typeName="int" … /><ECProperty propertyName="SpokeLength" typeName="double" … /><!--Unitized array of Doubles--><ECArrayProperty propertyName="SpokeTightness" typeName="double" minOccurs="0" maxOccurs="unbounded"><ECCustomAttributes><UnitSpecification xmlns="Unit_Attributes.01.00"><DimensionName>M_L2_PER_T2</DimensionName></UnitSpecification></ECCustomAttributes></ECArrayProperty></ECClass>
注意:
WheelHub属性,它被标识为ECStructProperty。struct属性具有由ECClass定义的复杂类型(在本例中为“Hub”类)。
还要注意SpokeTightness属性,它被标识为ecarray属性。通常,数组属性允许每个实例有多个(或更少)值。在这种情况下,给定实例中可以有任意数量的SpokeTightness值,如minOccurs=“0”和maxOccurs=“unbounded”所示。
最后,请注意SpokeTightness的含义已经使用UnitSpecification自定义属性进行了细化。此特定的自定义属性表示double类型SpokeTightness值应使用M_L2_PER_T2进行解释。
ECPropertyValue
ECPropertyValue表示ECInstance中单个ECProperty的值。在大多数情况下,ecpropertyValue组成一个ECInstance。
ECPropertyValue保存由ECProperty定义的各种类型的数据。例如:
基础类型值(string、integer、double…)
数组值
结构体值,它是由自己的ECClass定义的复杂结构体的值
结构体值的数组
计算值
几何对象值
注意:
关于ECPropertyValue的所有元信息都由ECProperty定义。
托管EC实现(ECPropertyValue始终是必需的并保存实际值)和非托管 的EC(可以直接访问值)之间存在一些差异。
ECSchema,ECClass,ECProperty,ECInstance,ECPropertyValue的理解
上面已经介绍了关于ECObject的各个部分的含义了,但是大家可能还是有些迷惑,如果单纯的从数据库的角度来理解或许能帮助大家更深入的明白其含义。
使用过数据库的同学都知道,在一个数据库里我们需要定义一个个表结构,然后呢我们可以通过代码不断的给每个表添加一行行的数据,或者修改各行的数据,或者删除各行的数据,又或者通过键值关联不同的表结构,其实这些和我们的EC框架是一样的。
在EC框架下
- ECRepository 就相当于整个数据库系统
- ECSchema 就相当于一个数据库的定义
- ECClass 就相当于一个数据库中表的定义
- ECProperty 就像是表结构中每一列的定义
- ECInstance 相当于每个表中的每一行。
- ECPropertyValue 就 相当于每一行中的每一个单元
- ECClass加上所产生的ECInstances 就相当于一个数据库所有的表格


ECRelationships
除了前面降到了ECObjects内容,还有一个关键的内容就是不同工程数据类型的“关系”,再EC框架里我们通过ECRelationships来处理,它就相当于一个第三方对象,关联了另外的两个工程对象。如下图所示:
在ECFramework中我们通过ECRelationshipClass 来定义“关系”,就像ECInstance 是通过ECClass定义一样。
ECRelationshipClass can “constrain” the ends:
ECClass constraint
“Cardinality” (Can there be one or many at that end?)
例如在ECClassEditor中:



用数据库的概念来说
ECRelationshipClass 就像是在数据库中定义了一个链接表格,ECRelationshipInstance 就是这个表格中的一行
ECXML概念介绍
ECXML是一个用XML格式用来表示工程数据(包含schema和instance数据)。其中“EC”代表工程内容。工程数据的信息模型很简单,事实上,它与SOAP(简单对象访问协议)中用于为工程数据建模的信息模型是相同的。
当整合来自不同系统的信息,通常最困难的任务是映射两个系统之间的数据结构和映射不同数据位的含义,由于需要集成的系统数量不断增加,ECXML试图定义一种通用的“通用语言”数据格式和术语,以帮助将集成任务从N个问题转换为N*1个问题。


ECXML遵循SOAP所使用的OO信息模型。这种OO范式可以很好地映射到.NET类型系统、W3C XML Schema类型系统以及像JSpace和ODS这样的Bentley系统。
ECSchemaXML and ECInstanceXML
我们的信息系统同时处理schema和instance数据。其中schema描述了数据的分类、结构等,它是实例数据的元数据。instance数据由构成实际业务信息的数据库行、业务对象等组成。因此,ECXML 分为两种XML 格式:ECSchemaXML和ECInstanceXML。
ECInstanceXML只是SOAP XML编码的一个简单变体。ECSchemaXML可以看作是数据库结构、JSpace类库、ODS结构、特征定义、三形式部分定义(或实体定义)的XML表示。给定的schema将描述特定专业业务领域的数据。
下面是一个ECXML模式的示例。它用于文件系统存储库ECPlugin(FSRECPlugin)。您不需要知道FSRECPlugin的详细信息,但是我们假设它是一个ECPlugin,它允许客户端应用程序通过ECServices API访问Windows文件系统数据。下面的模式使用了一些ECXML特性,这些特性可以让您更好地了解什么是ECSchema:
<?xml version="1.0" encoding="utf-16"?><ECSchemaschemaName="BentleyEcm"nameSpacePrefix="ecm"version="1.0"description="Contains core and base classes for Engineering Content concepts supported by most ECRepositories"displayLabel="Bentley ECM ECSchema"xmlns:bsca="Bentley_Standard_CustomAttributes.01.00"xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0"><ECSchemaReference name="Bentley_Standard_CustomAttributes" version="01.00" prefix="bsca" /> <ECCustomAttributes> <bsca:IdentificationOfStandardClasses> <bsca:ProjectBaseClass>Project</bsca:ProjectBaseClass> <bsca:DocumentBaseClass>Document</bsca:DocumentBaseClass><bsca:FolderBaseClass>Folder</bsca:FolderBaseClass> <bsca:FolderParentRelationshipClass>FolderParent</bsca:FolderParentRelationshipClass> <bsca:DocumentParentRelationshipClass>DocumentParent</bsca:DocumentParentRelationshipClass> </bsca:IdentificationOfStandardClasses> </ECCustomAttributes><ECClasstypeName="Document"description="Represents a document"isDomainClass="True"><ECProperty propertyName="Name" typeName="string" description="Name of the document" /><ECProperty propertyName="Filename" typeName="string" description="The file name" /><ECProperty propertyName="Description" typeName="string" description="Description" /></ECClass><ECClass typeName="DocumentInformation" isDomainClass="True" /><ECRelationshipClasstypeName="DocumentInformationOfDocument"isDomainClass="True"strength="embedding"strengthDirection="forward"><Source cardinality="(1,1)" roleLabel="Information about" polymorphic="True"> <Class class="DocumentInformation" /></Source><Target cardinality="(1,1)" roleLabel="described by" polymorphic="True"><Class class="Document" /></Target></ECRelationshipClass><ECClass typeName="Folder" description="Represents a folder" isDomainClass="True"><ECProperty propertyName="Name" typeName="string" description="Name of the folder" /><ECProperty propertyName="Description" typeName="string" description="Description" /></ECClass><ECRelationshipClasstypeName="DocumentParent"description="Relates a Document to the Folder that owns it."strength="embedding" strengthDirection="backward"><Source cardinality="(0,n)" roleLabel="contained in" polymorphic="True"><Class class="Document" /></Source><Target cardinality="(1,1)" roleLabel="contains" polymorphic="True"><Class class="Folder" /></Target></ECRelationshipClass><ECRelationshipClasstypeName="FolderParent"description="Relates a Folder to the Folder that owns it"strength="embedding"strengthDirection="backward"><Source cardinality="(0,n)" roleLabel="contained in" polymorphic="True"> <Class class="Folder" /> </Source><Target cardinality="(1,1)" roleLabel="contains" polymorphic="True"> <Class class="Folder" /> </Target></ECRelationshipClass><ECClass typeName="Project" description="Represents a Project." isDomainClass="True"><BaseClass>Folder</BaseClass></ECClass><ECClass typeName="ProjectInformation" description="Abstract base class for any ECClass representing information about a Project" isDomainClass="True" /><ECRelationshipClasstypeName="ProjectInformationOfProject"description="Relates ProjectInformation to the Project that owns it."isDomainClass="True"strength="embedding"strengthDirection="backward"><Source cardinality="(1,1)" roleLabel="Information about" polymorphic="True"><Class class="ProjectInformation" /></Source><Target cardinality="(1,1)" roleLabel="described by" polymorphic="True"><Class class="Project" /></Target></ECRelationshipClass></ECSchema>
Here is an explanation of some features that this ECSchema uses. It contains schema custom attributes:
<ECCustomAttributes><bsca:IdentificationOfStandardClasses><bsca:ProjectBaseClass>Project</bsca:ProjectBaseClass><bsca:DocumentBaseClass>Document</bsca:DocumentBaseClass><bsca:FolderBaseClass>Folder</bsca:FolderBaseClass><bsca:FolderParentRelationshipClass>FolderParent</bsca:FolderParentRelationshipClass><bsca:DocumentParentRelationshipClass>DocumentParent</bsca:DocumentParentRelationshipClass></bsca:IdentificationOfStandardClasses></ECCustomAttributes>
Those are used to specify attributes for the schema, such as ProjectBaseClass, which indicates that the ―Project‖ class is used as the project base class. You can also find ECClasses, such as the Folder class that contains two properties, Name and Description.
<ECClass typeName="Folder" description="Represents a folder" isDomainClass="True"><ECProperty propertyName="Name" typeName="string" description="Name of the folder" /><ECProperty propertyName="Description" typeName="string" description="Description" /></ECClass>
它还包含一些关系类,如DocumentParent,指示文档与其父级之间的关系,或者更具体地说,哪个文件夹包含给定的文档。在本例中,源类是Document,目标类是Folder。因此ECSchema的思想与数据库模式非常相似。它用于定义类、属性、关系类等。
Custom Attributes and Supplemented Schemas
自定义属性用于向schema、类或属性添加元信息。自定义属性是“ isCustomAttributeClass”参数设置为true的ECClass的实例。这个ECClass可以在当前schema中定义,也可以在当前schema所引用的schema中定义。在上面的例子中,一个自定义属性被分配到schema的顶层,这个自定义属性将标准概念(如文件夹类)映射到表示此schema中文件夹的类的名称。下面的例子如何定义自定义属性:
<ECClass typeName="IdentificationOfStandardClasses" isCustomAttributeClass="True"><ECProperty propertyName="ProjectBaseClass" typeName="string" /><ECProperty propertyName="FolderBaseClass" typeName="string" /><ECProperty propertyName="DocumentBaseClass" typeName="string" /><ECProperty propertyName="FolderParentRelationshipClass" typeName="string" /><ECProperty propertyName="ProjectParentRelationshipClass" typeName="string" /><ECProperty propertyName="DocumentparentRelationshipClass" typeName="string" /></ECClass>
实例化在被引用schema中定义的自定义属性时,实例必须使用完全限定的名称,或者必须引用该schema。在前面的IdentificationOfStandardClasses的完全限定名被使用。
<ECCustomAttributes><IdentificationOfStandardClasses xmlns="Bentley_Standard_CustomAttributes.01.00" ><ProjectBaseClass>Project</ProjectBaseClass><DocumentBaseClass>Document</DocumentBaseClass><FolderBaseClass>Folder</FolderBaseClass><FolderParentRelationshipClass>FolderParent</FolderParentRelationshipClass><DocumentParentRelationshipClass>DocumentParent</DocumentParentRelationshipClass></IdentificationOfStandardClasses></ECCustomAttributes>
自定义属性可以分配给实现IECCustomAttributeContainer接口的任何对象。因为ECSchema、ECClass和ECProperty都实现了这个接口,所以可以为它们分配自定义属性。可以分配给CustomAttributeContainer的自定义属性的数量没有限制,但是每个容器只能有一个自定义属性类的实例。例如,不能将两个IdentificationOfStandardClasses的自定义属性分配给ECSchema,但可以将一个分配给ECSchema,另一个分配给该ECSchema中的ECClass。(请注意,IdentificationOfStandardClasses的自定义属性不应应用于任何实际schema中的ECClass。)
ECServices 概念介绍
简单的说,ECServices是一个面向对象的工程内容API,它提供对电子文档(例如dgn文件、ProjectWise、SAP、SharePoint、eWarehouse等)的统一编程访问。它是一套新的.NET API,其固有的可扩展性使其成为访问各种内容存储库的框架……从dgn文件到ProjectWise集成和生命周期服务器,再到SAP和Oracle等第三方内容存储库。
ECServices本身并不真正知道如何访问存储库。真正的实现在EC-Plugins中,EC-Plugins是提供者(porvider)的集合,它们提供构成API的各种服务的实现。ECServices是ECFramework的一个主要部分,其它的部分包括ECObjects、ECXML、ECPropertyEnablers和MicroStation中的PropertyManager、ECClassEditor等。ECServices高度依赖于ECObjects和ECXML,但它们并不依赖于ECServices。
ECServices的最初目标和设计原则
1.使用一个通用API支持多个存储库
有时我们称之为“数据源无关”或“存储库无关”API,用于完成查询对象、持久化对象、导航对象层次结构等基本操作,ECServices提供了一个公共API,可以提供对各种存储库类型的访问,这样就可以编写应用程序,而不需要知道存储库的具体信息。它们通过存储库ECPlugin以一种常见的方式访问存储库。
2. 普遍可扩展性
ECServices中的可扩展性是一种指导性的设计模式,而不是事后的想法。ECServices本身无法管理任何内容所有真正的功能都是由通过可扩展性基础设施插入框架的“提供者”实现的。支持扩展性的方法是允许扩展程序注册实现.NET接口的类,这些接口是某些服务通过事件钩子查找的。
部署灵活性
ECServices最终将支持灵活的部署(桌面、断开连接模式、富客户机或瘦客户机),方法是遵循一种面向服务的体系结构,具有明确的分离、可重新配置的层。操作在代理、服务器和实用程序类中实现,而数据保存在信息保持类中,必要时可以作为消息在层之间传递。该API旨在促进代理和服务器之间的大量(而不是聊天)通信,以便在网络上获得更好的性能。文档和组件
从根本上讲,通过ECServices访问的所有业务对象都是相同的,无论它们表示工程组件/资产还是文档和文件夹。“文档”只是一个由“文件支持”的文件。我们只在实际需要处理相关联的文件时,才会对“文件支持”的实例进行不同的处理。最小API——表面积
ECServices API被设计为具有一个精益API。它通过使用一个基于ECObjectbased的API来为所有ECClasses的托管对象执行持久化、查询和表示等通用服务,并尽可能像对待其他对象一样处理文档和文件夹。
6. 元数据驱动
ECServices由元数据(主要以ECSchema形式表示)驱动,元数据可以扩展为垂直行业、顾问和客户。从长远来看,更少的硬编码逻辑(通过更多的元数据驱动逻辑)会导致更小的代码库和更少的代码维护,更不用说它提供的灵活性和可扩展性了。
ECServices 架构
ECServices是“面向服务的”。这并不意味着ECServices正在使用Web服务或NT服务等,我们使用的单词“服务”只不过是一个小的、内聚的、解耦的API,它负责处理由“信息保持”对象保存的信息。这种面向对象设计的特殊变化对于灵活的部署和可扩展性来说是最佳的,并且在所有层都是“进程中”以及“客户机-服务器”和“三层”配置的情况下可以很好地工作。
简单的说ECServices 就是被应用程序访问EC资源库的一套API,主要包含了一下几个方面的功能
-查询对象(所有内容都被视为一个ECObject)
- 持久化对象中的更改
- 浏览(浏览对象层次结构)
- 查看(查看对象的内容或详细信息)
- 访问文件(get和put)
- 处理配置、日志记录、可扩展性等。
对于ECServices自己来说它就是一套统一的API接口,它自身并不知道有哪些EC资源库,有哪些数据格式等等,而这些EC数据都是通过ECObjects来获取和控制的,因此整个ECFramework框架的核心就是ECObjects和ECServices。
ECServices 采用了SOA架构(Service-Oriented Architecture),这种架构常用于WebServices,这种架构模式让ECFramework更加的灵活。
ECPlugins 介绍
到目前为止,我们了解到ECXML和ECObjects是业务数据的具体表示。因此,为了实现互操作性的目标,我们希望能够用这种通用表示法来表示存储在任何存储库中的数据。为此,我们需要为想要访问的任何存储库创建一个ECPlugin。举个例子,ECPlugins适用于Windows文件系统存储库(FsrECPlugin)、DGN文件(DGNECPlugin)、Projectwise(PWECPlugin)和其他一些ECRepositories。顺便说一句,从现在开始,让我们使用约定来命名―ECRepository,任何可以通过ECPlugin访问的存储库。下图显示了两个访问ProjectWise ECRepository和文件系统ECRepository的客户端应用程序。这两个ECPlugins都将数据作为本机数据检索并存储到各自的ecrepository中。客户端应用程序通过ECObjects从ECPlugins交换数据。当应用程序需要在它们之间交换数据时,它们通常需要序列化数据,这是使用ECXML完成的。因此,ECXML可以看作是序列化的ECObjects。同样,必须持久化的ECObjects也可以作为ECXML持久化。
EC 的使用
前面的几个章节已经基本介绍了整套EC框架的基本概念,但是真正在使用的时候我们不需要使用到这么多的内容,尤其是在基于Microstation的平台上的软件,因为Bentley已经帮助大家在把大部分的操作已经实现了,大家只需要简单的调用就可以扩展自己的EC数据了,下面几个部分就是在Microstation的使用EC的方法的介绍。
在Microstation平台了,首先是提供了一个DGNECPlugin的服务插件DGNECPlugin,通过这个插件就相当于把DGN文件作为ECRepository暴露给大家使用。大家可以通过通用的EC服务类函数来增加,删除,修改和查询DGN文件中的EC数据,同时Bentley为了进一步简化这些调用的方法封装了一个DgnECManager类,这个类里包含了所有的对于DGN文件中的EC数据的增删改查的操作。
下图是一个常用的使用流程
配置
要在MicroStation,OpenRoads等设计应用软件中使用DGNECPlugin首先要确保中使用DGNECPlugin必须确保 已经加载Bentley.DgnECPlugin[3].dll.不过不同意其他ecplugin这个DLL目前会跟随MS自动加载,大家不需要做任何配置可以直接使用。
当MicroStation中已经加载了DGNECPlugin后,我们便可以通过DgnECManager.Manager 来进行EC相关的操作了。
Schema 定义
前面已经讲过,工程数据的定义是通过scheam来定义,Bentley提供了ECCLASS EDIT来定义Schema,不过用户也可以直接通过代码来定义
例如:
string schemaXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+ "<ECSchema schemaName=\"ComplexSchema\" nameSpacePrefix=\"ComplexSchema\" version=\"1.0\" xmlns=\"http://www.bentley.com/schemas/Bentley.ECXML.2.0\">"+ " <ECClass typeName=\"Contact\" isStruct=\"True\" isDomainClass=\"False\">"+ " <ECProperty propertyName=\"Name\" typeName=\"string\" /> "+ " <ECProperty propertyName=\"Age\" typeName=\"int\" /> "+ " <ECArrayProperty propertyName=\"PhoneNumber\" typeName=\"string\" /> "+ " </ECClass>"+ " <ECClass typeName=\"StructClass\" isStruct=\"True\" isDomainClass=\"False\">"+ " <ECProperty propertyName=\"StringProperty\" typeName=\"string\" /> "+ " <ECProperty propertyName=\"IntProperty\" typeName=\"int\" /> "+ " <ECArrayProperty propertyName=\"ArrayProperty\" typeName=\"string\" minOccurs=\"1\" maxOccurs=\"1\" /> "+ " <ECArrayProperty propertyName=\"ContactData\" typeName=\"Contact\" isStruct=\"True\" /> "+ " </ECClass>"+ " <ECClass typeName=\"ComplexClass\" isDomainClass=\"True\">"+ " <ECProperty propertyName=\"IntProperty\" typeName=\"int\" />"+ " <ECProperty propertyName=\"StringProperty\" typeName=\"string\" /> "+ " <ECProperty propertyName=\"DoubleProperty\" typeName=\"double\" /> "+ " <ECProperty propertyName=\"DateTimeProperty\" typeName=\"dateTime\" />"+ " <ECProperty propertyName=\"BooleanProperty\" typeName=\"boolean\" />"+ " <ECProperty propertyName=\"APoint2d\" typeName=\"point2d\" />"+ " <ECProperty propertyName=\"APoint3d\" typeName=\"point3d\" />"+ " <ECProperty propertyName=\"ALong\" typeName=\"long\" />"+ " <ECProperty propertyName=\"ABinary\" typeName=\"binary\" />"+ " <ECArrayProperty propertyName=\"SimpleArrayProperty\" typeName=\"string\"/>"+ " <ECArrayProperty propertyName=\"FixedArrayProperty\" typeName=\"string\" minOccurs=\"1\" maxOccurs=\"1\" />"+ " <ECArrayProperty propertyName=\"StructArrayProperty\" typeName=\"StructClass\" isStruct=\"True\" />"+ " <ECArrayProperty propertyName=\"FixedStructArrayProperty\" typeName=\"StructClass\" minOccurs=\"1\" maxOccurs=\"1\" isStruct=\"True\" />"+ " <ECStructProperty propertyName=\"StructProperty\" typeName=\"StructClass\" />"+ " </ECClass>"+ "</ECSchema>";ECSchemaXmlStringReader xmlReader = new ECSchemaXmlStringReader(schemaXml);IECSchema deserializedSchema = xmlReader.Deserialize();
或者
IECSchema schema = new ECSchema(SCHEMA_NAME, SCHEMA_MAJOR, SCHEMA_MINOR, "");//create the Project classECClass prjClass = new ECClass(PROJECT_CLASS);prjClass.Add(new ECProperty(PROJECT_PROP_PARENTPRJID, Bentley.ECObjects.ECObjects.IntegerType));prjClass.Add(new ECProperty(PROJECT_PROP_NAME, Bentley.ECObjects.ECObjects.StringType));prjClass.Add(new ECProperty(PROJECT_PROP_COST, Bentley.ECObjects.ECObjects.DoubleType));prjClass.IsCustomAttribute = false;prjClass.IsDomainClass = true;schema.AddClass(prjClass);//create the Member classECClass memberClass = new ECClass(MEMBER_CLASS);memberClass.Add(new ECProperty(MEMBER_PROP_NAME, Bentley.ECObjects.ECObjects.StringType));memberClass.Add(new ECProperty(MEMBER_PROP_PROJECTID, Bentley.ECObjects.ECObjects.IntegerType));memberClass.Add(new ECProperty(MEMBER_PROP_ROLE, Bentley.ECObjects.ECObjects.StringType));memberClass.IsCustomAttribute = false;memberClass.IsDomainClass = true;schema.AddClass(memberClass);
Schema的加载
定义完工程数据后我们需要把他们加载到资源库中也就是DGN文件中,然后才能使用。
加载的方式如下:
//1.首先要在电脑中创建一个ecschema的XML文件,例如 C://ECTEST//ComplexSchema.01.00.ecschema.xml//2.定义schema的内容//<ECSchema schemaName=\"ComplexSchema\" nameSpacePrefix=\"ComplexSchema\" version=\"1.0\" xmlns=\"http://www.bentley.com/schemas/Bentley.ECXML.2.0\">//<ECClass typeName=\"Contact\" isStruct=\"True\" isDomainClass=\"False\">// <ECProperty propertyName=\"Name\" typeName=\"string\" />// <ECProperty propertyName=\"Age\" typeName=\"int\" />// <ECArrayProperty propertyName=\"PhoneNumber\" typeName=\"string\" />//</ECClass>// ..................//</ECSchema>;//3.加载到dgn文件Public void ImportSchemaToDgnFile (DgnFile importfile){string searchpath = “C://ECTEST//”;IECSchemaLocater SearchPathLocater = new SearchPathSchemaFileLocater(searchpath);Bentley.ECObjects.ECObjects.AddSchemaLocater(SearchPathLocater);string schemafullname = "ComplexSchema.01.00";IECSchema TestSchema =Bentley.ECObjects.ECObjects.LocateSchema(schemafullname, SchemaMatchType.Exact, null, null);DgnECManager dgnECManager = DgnECManager.Manager;SchemaImportStatus impStatus = DgnECManager.Manager.ImportSchema(TestSchema, importfile, opt);}
Schema 的更新
public void UpdateSchemaToDgnFile(DgnFile importfile,IECSchema uschema){UpdateSchemaOptions uoption = new UpdateSchemaOptions();SchemaUpdateStatus ustatus = DgnECManager.Manager.UpdateSchema(uschema, importfile, uoption);if (ustatus == SchemaUpdateStatus.Success){MdlUtils.DGNContext.StatusMessage("数据升级完成");}else{MdlUtils.DGNContext.StatusMessage("数据升级:" + ustatus.ToString());}}
Schema的查找
对于已经导入到DGN文件中的schema我们可以通过查找函数来找到这些schema
Bentley.DgnPlatformNET.DgnEC.DgnECManager ecManager = Bentley.DgnPlatformNET.DgnEC.DgnECManager.Manager;foreach (string schemaName in ecManager.DiscoverSchemas(activeFile, DgnPlatformNET.DgnEC.ReferencedModelScopeOption.None, false)){string name = schemaName.Substring(0, schemaName.IndexOf('.'));}
查询ECClass
当我们有了IECSchema对象实例后,便可以通过他提供的函数找到对应的工程数据类
IECClass[] GetClasses();
IECClass GetClass(string className);
查询ECInstance
在microstation中,所有的EC数据都是通过元素来存储的,所以我们也需要通过元素来获取对应的EC数据,例如
ECInstanceList eclist = new ECInstanceList();StringBuilder str = new StringBuilder();Bentley.DgnPlatformNET.DgnModel dm = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();Bentley.DgnPlatformNET.ModelElementsCollection eles = dm.GetGraphicElements();foreach (Bentley.DgnPlatformNET.Elements.Element ei in eles){DgnECInstanceCollection DC = DgnECManager.Manager.GetElementProperties(ei, ECQueryProcessFlags.SearchAllClasses);foreach (IDgnECInstance instance in DC){eclist.Add(instance);str.AppendLine(instance.ClassDefinition.Name);}}
创建ECInstance
在
public IECInstance CreateDesInstance (IECClass ecClass,string name, string des){IECInstance ecInstance = ecClass.CreateInstance();ecInstance ["Name"].StringValue = name;ecInstance ["Des"].StringValue = des;return chairInstance;}
保存ECInstance
在MicroStation要保存EC数据到DGN文件中需要关联元素或者模型
public IDgnECInstance SaveECInstanceOnElemen(Element element, IECInstance instance){try{DgnFile dgnfile = element.DgnModel.GetDgnFile();IECClass ecClass = instance.ClassDefinition;DgnECInstanceEnabler instanceEnabler = DgnECManager.Manager.ObtainInstanceEnabler(dgnfile, ecClass);StandaloneECDInstance wipInstance = instanceEnabler.SharedWipInstance;IDgnECInstance instanceOnElement = instanceEnabler.CreateInstanceOnElement(element, wipInstance, false);return instanceOnElement;}catch (Exception ex){Bentley.MstnPlatformNET.MessageCenter.Instance.StatusMessage = ex.Message;Bentley.MstnPlatformNET.MessageCenter.Instance.StatusWarning = ex.Message;}return null;}
对于model的EC属性可以通过下面的方法
DgnFile dgnfile = model.GetDgnFile();IECClass ecClass = instance.ClassDefinition;DgnECInstanceEnabler instanceEnabler = DgnECManager.Manager.ObtainInstanceEnabler(dgnfile, ecClass);StandaloneECDInstance wipInstance = instanceEnabler.SharedWipInstance;DgnECManager.CopyInstanceData(wipInstance, instance);IDgnECInstance instanceOnElement = instanceEnabler.CreateInstanceOnModel(model, wipInstance);StatusInt stat = model.GetDgnFile().ProcessChanges(DgnSaveReason.ApplicationInitiated);if (stat == StatusInt.Success && instanceOnElement != null){Bentley.MstnPlatformNET.MessageCenter.Instance.StatusMessage = "Success_Save_Model_Instance";}
修改ECInstance
public void UpdateModelInstance(IDgnECInstance instance, DgnModel model){instance.WriteChanges();model.GetDgnFile().ProcessChanges(DgnSaveReason.ApplicationInitiated);}
删除ECInstance
public void DeletedModelInstance(IDgnECInstance instance, DgnModel model){try{instance.Delete();model.GetDgnFile().ProcessChanges(DgnSaveReason.ApplicationInitiated);}catch (Exception ex){Bentley.MstnPlatformNET.MessageCenter.Instance.StatusMessage = ex.Message;Bentley.MstnPlatformNET.MessageCenter.Instance.StatusWarning = ex.Message;}}
Item Type技术
Item Type是基于EC技术开发的更容易使用的功能,是EC的简化形式。它可以附加到元素、模型和文件上。Item Type是一个ECClass,它支持ECClass可用特性的子集。与原始的ECCLASS相比,Item Type具有下面的一些区别:
1.不支持继承;
2.为每个基元属性提供默认值;
3.不支持大多数自定义属性
4.仅支持部分可用属性类型CustomProperty::Type;
5. 可由基于Item Type的工具使用,如MicroStation的“附加项目”工具;
Item Type存储在一个Item Type类型库中,该库是一个类似的受限ECSchema。与原始的ecschema相比,Item Type具有下面的一些特性:
1.只能引用标准架构(主要用于自定义属性);
2.不支持大多数自定义属性;
3.无法定义自定义属性类;
4.用户可以自由修改、删除、更新和重命名;
CustomProperty
将ItemType附加到主机以生成项(Item)时,每个CustomProperty成为项(Item)中的属性值。
每个CustomProperty都有下面特征:
1.它的名称具有唯一性,这个名称也是是用户所看到的名称,并且是并且属性的主标识符。
2.它会产生一个用户永远看不到的唯一内部名称和ID。
3.它所支持的类型包括integer、boolean或string。
4.它能够设置属性显示的优先级,以便控制属性在UI中的显示顺序。
5.可以指定某个单位用来表示属性中的值,Double类型的属性可以作为任何类型属性的单位,Point类型的属性可以 长度类型属性的单位,
6. 为属性指定一个默认值。
ItemType
ItemType是定义CustomProperties的命名集合,它可以定义附加到元素、模型和文件(DgnFile)。
ItemType可以“附加”到主体,例如图元、模型或DgnFile。这就产生了一个“项”(Item),其中每个ItemType的CustomProperty定义都成为一个属性,项中的每个值都将根据对应的CustomProperty设置的默认值进行初始化。
ItemTypeLibrary
ItemTypeLibrary定义ItemTypes和CustomPropertyTypes的命名集合。每个库都有其包含在DgnFile中的唯一名称。
下面具体给出了一个完整的Item Type的例子,该例子包括创建、修改及删除Item Type:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using Bentley.GeometryNET;
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.DgnPlatformNET.DgnEC;
using Bentley.MstnPlatformNET;
using Bentley.ECObjects;
using Bentley.ECObjects.Schema;
using Bentley.ECObjects.Instance;
namespace MSAppNET
{
class ItemTypeTest
{
public static void CreateItemType(string itemLibName, string itemTypeName)
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);
if (null == itemTypeLibrary)
{
itemTypeLibrary = ItemTypeLibrary.Create(itemLibName, dgnFile);
}
itemTypeLibrary.AddItemType(itemTypeName);
ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);
CustomProperty intProperty = itemType.AddProperty(“IntProperty”);
intProperty.Type = CustomProperty.TypeKind.Integer;
CustomProperty strProperty = itemType.AddProperty(“StrProperty”);
strProperty.Type = CustomProperty.TypeKind.String;
itemTypeLibrary.Write();
}
//删除<br /> public static void DeleteItemType(string itemLibName, string itemTypeName)<br /> {<br /> DgnFile dgnFile = Session.Instance.GetActiveDgnFile();<br /> ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);<br /> if (null == itemTypeLibrary)<br /> {<br /> MessageBox.Show("Can't find itemType library!");<br /> return;<br /> }<br /> ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);<br /> itemTypeLibrary.RemoveItemType(itemType);<br /> itemTypeLibrary.Write();<br /> }<br /> //附加元素<br /> public static void AttachItem(string itemLibName, string itemTypeName, ElementId elemId)<br /> {<br /> DgnModel dgnModel = Session.Instance.GetActiveDgnModel();<br /> Element elem = dgnModel.FindElementById(elemId);<br /> if (null == elem)<br /> {<br /> MessageBox.Show("Can't find element!");<br /> return;<br /> }DgnFile dgnFile = Session.Instance.GetActiveDgnFile();<br /> ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);<br /> if (null == itemTypeLibrary)<br /> {<br /> MessageBox.Show("Can't find ItemType Library");<br /> return;<br /> }<br /> ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);CustomItemHost host = new CustomItemHost(elem, true);<br /> IDgnECInstance item = host.ApplyCustomItem(itemType, true);<br /> item.SetValue("IntProperty", 123);<br /> item.SetValue("StrProperty", "CCCC");item.ScheduleChanges(elem);<br /> elem.ReplaceInModel(elem);<br /> }<br /> // ECNameValidation.EncodeToValidName has bug in C#, correct in nativeCode C++<br /> private static string FurtherConvert(string inStr)<br /> {<br /> string rtnStr = inStr;<br /> string pa = @"^[a-zA-Z0-9]*$";<br /> Regex reg = new Regex(pa);<br /> Match mc = null;<br /> for (int i = 0; i < rtnStr.Length - 4; i++)<br /> {<br /> if (rtnStr.Substring(0, 2) == "__")<br /> {<br /> string curMiddleStr = "";<br /> int j = i + 2;<br /> for (; j < rtnStr.Length; j++)<br /> {<br /> if (rtnStr[j] == '_')<br /> {<br /> curMiddleStr = rtnStr.Substring(i + 2, j - (i + 2));<br /> break;<br /> }<br /> }<br /> if (j > rtnStr.Length - 2)<br /> {<br /> break;<br /> }<br /> mc = reg.Match(curMiddleStr);<br /> if (mc.Success)<br /> {<br /> if (rtnStr.Substring(j, 2) == "__")<br /> {<br /> string curTempStr = rtnStr.Substring(i, j + 2 - i);<br /> if (curTempStr.Length == 9 && curTempStr[2] == 'x')<br /> {<br /> curTempStr = "__x" + curTempStr.Substring(3).ToUpper();<br /> rtnStr = rtnStr.Substring(0, i - 0) + curTempStr + rtnStr.Substring(j + 2, rtnStr.Length - j - 2);<br /> }<br /> }<br /> }<br /> }<br /> }<br /> return rtnStr;<br /> }//读取属性<br /> public static void ReadItem(string itemLibName, string itemTypeName, ElementId elemId)<br /> {<br /> DgnModel dgnModel = Session.Instance.GetActiveDgnModel();<br /> Element elem = dgnModel.FindElementById(elemId);<br /> if (null == elem)<br /> {<br /> MessageBox.Show("Can't find element!");<br /> return;<br /> }<br /> CustomItemHost host = new CustomItemHost(elem, true);<br /> IDgnECInstance item = host.GetCustomItem("ItemTypeLib", "MyItemType");DgnFile dgnFile = Session.Instance.GetActiveDgnFile();<br /> ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName("ItemTypeLib", dgnFile);<br /> ItemType itemType = itemTypeLibrary.GetItemTypeByName("MyItemType");<br /> CustomProperty property = itemType.GetPropertyByName("编码");<br /> string internalName = property.InternalName;<br /> IECPropertyValue val = item.GetPropertyValue(internalName);<br /> MessageBox.Show(val != null ? val.StringValue : "val==null");<br /> }<br /> public static void DetachItem(string itemLibName, string itemTypeName, ElementId elemId)<br /> {<br /> DgnModel dgnModel = Session.Instance.GetActiveDgnModel();<br /> Element elem = dgnModel.FindElementById(elemId);<br /> Element newElem = elem;<br /> CustomItemHost host = new CustomItemHost(newElem, true);<br /> IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);item.ScheduleDelete(newElem);<br /> newElem.ReplaceInModel(elem);<br /> }<br /> }<br />}
