Сохранение порядка в последовательности выбора (LINQ To XSD)
Учитывая следующий пример XML, мы могли бы представить схему, определяющую Root как содержащую последовательность несвязанного числа вариантов выбора между Type1 и Type2.
<Root>
<Type1 />
<Type2 />
<Type2 />
<Type1 />
</Root>
Я тестирую миграцию с помощью инструмента XSD.exe, который, хотя и добавляет безопасность типов, имеет много небольших неприятностей. Инструмент XSD в этом случае просто создает в Root массив типа System.Object, и вы должны выяснить, какие типы объектов (Type1 или Type2) находятся там. Это не совсем элегантно, но, по крайней мере, вы сохраняете порядок.
Проблема в том, что когда LINQ to XSD создает объекты, он определяет Root как наличие двух независимых списков Type1 и Type2. Это здорово, потому что это типобезопасно, но теперь я, похоже, теряю порядок элементов. Я построил LINQ to XSD из исходного кода на codeplex.
Используя LINQ to XSD, как я могу сохранить порядок этих элементов?
2 ответа
Как насчет создания оболочки вокруг Choice? Ограничение типов, к которым он получает доступ следующим образом:
class Choice
{
private object _value;
public ChoiceEnum CurrentType { get; private set; }
public Type1 Type1Value
{
get { return (Type1) _value; }
set { _value = value; CurrentType = ChoiceEnum.Type1; }
}
public Type2 Type2Value
{
get { return (Type2) _value; }
set { _value = value; CurrentType = ChoiceEnum.Type2; }
}
}
Это упрощенная версия, и вам придется добавить дополнительную проверку (если _value
имеет правильный тип, каков текущий тип _value
, так далее).
Затем вы можете отфильтровать его с помощью LINQ:
var q1 = from v in root.Sequence
where v.CurrentType == ChoiceEnum.Type1
select v.Type1;
Или вы можете создать методы в Root, которые будут оборачивать запросы.
Linq2Xsd срабатывает только на последовательности, когда есть элемент xsd:choice.
К счастью, я смог удалить xsd:choice для используемого мной Amazon XSD (я просто не использовал MerchantOrderID), что позволило правильно сохранить последовательность в ToString()
для XML.
<xsd:choice> <--- removed line
<xsd:element ref="AmazonOrderID"/>
<xsd:element ref="MerchantOrderID"/> <--- removed line
</xsd:choice> <--- removed line
<xsd:element name="ActionType" minOccurs="0" maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Refund"/>
<xsd:enumeration value="Cancel"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
Затем сгенерированный код правильно имеет это в конструкторе, который сохраняет порядок
contentModel = new SequenceContentModelEntity(
new NamedContentModelEntity(XName.Get("AmazonOrderID", "")),
new NamedContentModelEntity(XName.Get("ActionType", "")),
new NamedContentModelEntity(XName.Get("CODCollectionMethod", "")),
new NamedContentModelEntity(XName.Get("AdjustedItem", "")));
Вы также можете сделать это вручную, подклассифицируя это самостоятельно, но я не уверен, как это будет работать с xsd:choice. Это описано здесь, но я не проверял это.