Как внедрить EXPRESS в CSharp наиболее эффективно
Мне нужно создать библиотеку классов на основе схемы EXPRESS. Схема EXPRESS имеет типы и сущности, похожие на следующие:
ENTITY IfcRoot
ABSTRACT SUPERTYPE OF (ONEOF
(IfcObjectDefinition
,IfcPropertyDefinition
,IfcRelationship));
GlobalId : IfcGloballyUniqueId;
OwnerHistory : OPTIONAL IfcOwnerHistory;
Name : OPTIONAL IfcLabel;
Description : OPTIONAL IfcText;
UNIQUE
UR1 : GlobalId;
END_ENTITY;
Здесь GlobalId, OwnerHistory, Name и Description - все это свойства класса IfcRoot. Например, тип свойства "Имя" - это IfcLabel, который задается как ТИП в схеме EXPRESS и выглядит следующим образом:
TYPE IfcLabel = STRING(255);
END_TYPE;
Этот тип имеет тип String или массив строк. В моем подходе я реализовал все сущности в схеме и все типы в схеме как классы в chsharp. Поэтому я написал программу чтения строк, которая читает схему и создает на ее основе сущности (~800) и типы (~400). IfcLabel в моей реализации выглядит так:
public class IfcLabel
{
public string _value { get; set; }
}
Все это прекрасно работает, но когда я хочу использовать свою библиотеку классов, это действительно трудоемко из-за того факта, что каждый тип атрибута является самим классом. Это значит, что я должен сначала создать объект класса IfcLabel и назначить свойство _value, а затем создать свой объект IfcRoot и назначить свойство Name как объект IfcLabel. У кого-нибудь есть идея, как я могу реализовать это умнее? Следует добавить еще одну вещь: все типы должны иметь метод и наследоваться от класса с именем IfcBase, так что это все еще должно быть возможным. Мне также не разрешается напрямую изменять тип свойства с IfcLabel на строку, что в любом случае оно и есть.
2 ответа
Чтобы упростить IfcLabel, вы можете использовать неявную перегрузку операторов, чтобы можно было рассматривать IfcLabel как String
, без Name._value
через ваш код.
Если это больше, чем образовательный проект, возможно, стоит посмотреть, как другие справились с этим. Например, проект Xbim имеет библиотеки C# для чтения и записи файлов IFC. Для справки вот их реализация IfcRoot и IfcLabel:
https://github.com/xBimTeam/XbimEssentials/blob/master/Xbim.Ifc4/Kernel/IfcRoot.cs#L58 https://github.com/xBimTeam/XbimEssentials/blob/master/Xbim.Ifc4/MeasureResource/IfcLabel.cs
Если вам действительно нужно работать с файлами IFC EXPRESS на коммерческой основе, я могу порекомендовать посмотреть на закаленную в боях библиотеку, такую как XBim или IfcOpenShell, поскольку это сложный домен, чтобы писать свои собственные с нуля.
Все еще не хорошо, но по крайней мере немного лучше, потому что я могу сложить всю декларацию объекта, чтобы она выглядела немного яснее в Visual Studio, я сделал это:
IfcAlignment2DVerSegLine ifcVerSegLine = new IfcAlignment2DVerSegLine()
{
m_StartDistAlong = new IfcLengthMeasure()
{
_value = verTangent.StartStation
},
m_HorizontalLength = new IfcPositiveLengthMeasure()
{
_value = new IfcLengthMeasure()
{
_value = verTangent.Length
}
},
m_StartGradient = new IfcRatioMeasure()
{
_value = verTangent.Grade
},
m_StartHeight = new IfcLengthMeasure()
{
_value = verTangent.StartElevation
}
};
складывается в:
IfcAlignment2DVerSegLine ifcVerSegLine = new IfcAlignment2DVerSegLine()...;
Так что это работает для моей цели на данный момент. Конечно, если этот продукт когда-либо станет коммерческим, мне придется переписать свое раннее связывание.