xsd.exe生成的c#在一个数组中包含多个元素

xsd.exe生成的c#在一个数组中包含多个元素,c#,xml,xsd,C#,Xml,Xsd,我有一组XML模式文件提供给我。我无法更改XML,因为它们有时会更新。我正在使用xsd.exe将模式文件转换为生成的c#代码。我不能使用任何第三方工具。其中一个XML架构文件的一部分如下所示: <xs:complexType name="LocationType"> <xs:choice minOccurs="1" maxOccurs="1"> <xs:element name="LocNum" minOccurs="1" maxOccurs="1" t

我有一组XML模式文件提供给我。我无法更改XML,因为它们有时会更新。我正在使用xsd.exe将模式文件转换为生成的c#代码。我不能使用任何第三方工具。其中一个XML架构文件的一部分如下所示:

<xs:complexType name="LocationType">
  <xs:choice minOccurs="1" maxOccurs="1">
    <xs:element name="LocNum" minOccurs="1" maxOccurs="1" type="xs:string" />
    <xs:sequence>
      <xs:element name="Name" minOccurs="0" maxOccurs="1" type="xs:string" />
      <xs:element name="Address" minOccurs="0" maxOccurs="1" type="xs:string" />
      <xs:element name="City" minOccurs="1" maxOccurs="1" type="xs:string" />
      <xs:element name="State" minOccurs="0" maxOccurs="1">
    </xs:sequence>
  </xs:choice>
</xs:complexType>

该模式所说的是,如果某个外部类型包含类型为
LocationType
的元素,则可以在其中找到

1) 子元素
,或

2) 这些子元素按顺序排列:
属性,在本例中为
ItemsElementName
。此数组中的条目必须与
数组1-1对应。它通过
ItemsChoiceType
枚举记录在
Items
数组的每个索引中反序列化的元素的名称,其枚举名称必须与装饰
Items
数组的属性中的名称相匹配。这使得多态数据的具体选择是已知的

因此,要完善
LocationType
类的实现,您需要确定给定的
LocationType
是直接的还是间接的;拿出各种财产;对于每种类型(直接或间接),设置所有必需的数据

这是一个原型。(您的问题中没有包含
LocationTypeState
的定义,因此我将其视为一个字符串):

public分部类LocationType
{
公共位置类型(){}
公共位置类型(字符串locNum)
{
SetIndirectLocation(locNum);
}
公共位置类型(字符串名称、字符串地址、字符串城市、字符串状态)
{
SetDirectLocation(名称、地址、城市、州);
}
公共广播是间接定位的
{
得到
{
返回Array.IndexOf(ItemsElementName,ItemsChoiceType.LocNum)>=0;
}
}
公共字符串地址{get{return(string)XmlPolymorphicCarrayHelper.GetItem(Items,ItemsElementName,ItemsChoiceType.Address);}
公共字符串LocNum{get{return(string)xmlmorphicalarayhelper.GetItem(Items,ItemsElementName,ItemsChoiceType.LocNum);}
//其他需要的属性。
public void SetIndirectLocation(字符串locNum)
{
if(string.IsNullOrEmpty(locNum))
抛出新ArgumentException();
object[]newItems=新对象[]{locNum};
ItemsChoiceType[]newItemsElementName=new ItemsChoiceType[]{ItemsChoiceType.LocNum};
this.Items=newItems;
this.ItemsElementName=newItemsElementName;
}
public void SetDirectLocation(字符串名称、字符串地址、字符串城市、字符串状态)
{
//在模式中,“城市”是必需的,其他是可选的。
if(string.IsNullOrEmpty(城市))
抛出新ArgumentException();
List newItems=新列表();
List newItemsElementName=newlist();
if(name!=null)
{
newItems.Add(名称);
添加(ItemsChoiceType.Name);
}
if(地址!=null)
{
新增项目。添加(地址);
newItemsElementName.Add(ItemsChoiceType.Address);
}
newItems.Add(城市);
添加(ItemsChoiceType.City);
如果(状态!=null)
{
newItems.Add(state);
newItemsElementName.Add(ItemsChoiceType.State);
}
this.Items=newItems.ToArray();
this.ItemsElementName=newItemsElementName.ToArray();
}
}
公共静态类xmlayHelper
{
公共静态TResult GetItem(TResult[]项,TIDentifier[]项标识符,TIDentifier项标识符)
{
if(itemIdentifiers==null)
{
Assert(items==null);
返回默认值(TResult);
}
Assert(items.Length==itemIdentifiers.Length);
var i=Array.IndexOf(itemIdentifier,itemIdentifier);
if(i<0)
返回默认值(TResult);
退货项目[i];
}
}

这是我从原始答案中学到的最终解决方案。此静态类用于获取和设置适当的属性

public static class XmlPolymorphicArrayHelper
{
    public static TResult GetItem<TIDentifier, TResult>(TResult[] items, TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier)
    {
        if (itemIdentifiers == null)
        {
            return default(TResult);
        }
        var i = Array.IndexOf(itemIdentifiers, itemIdentifier);
        return i < 0 ? default(TResult) : items[i];
    }

    public static void SetItem<TIDentifier, TResult>(ref TResult[] items, ref TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier, TResult value)
    {
        if (itemIdentifiers == null)
        {
            itemIdentifiers = new[] { itemIdentifier };
            items = new[] { value };

            return;
        }

        var i = Array.IndexOf(itemIdentifiers, itemIdentifier);
        if (i < 0)
        {
            var newItemIdentifiers = itemIdentifiers.ToList();
            newItemIdentifiers.Add(itemIdentifier);
            itemIdentifiers = newItemIdentifiers.ToArray();

            var newItems = items.ToList();
            newItems.Add(value);
            items = newItems.ToArray();
        }
        else
        {
            items[i] = value;
        }

    }
}
这将在Items数组上设置/创建适当的成员,我可以将其用于实现此模式的多个类

public partial class LocationType
{
    public string Address
    {
        get
        {
            // code here to return the correct Items[] element
        }
        set
        {
            // code here to set the correct Items[] element
        }
    }
}
public partial class LocationType
{
    public LocationType() { }

    public LocationType(string locNum)
    {
        SetIndirectLocation(locNum);
    }

    public LocationType(string name, string address, string city, string state)
    {
        SetDirectLocation(name, address, city, state);
    }

    public bool IsIndirectLocation
    {
        get
        {
            return Array.IndexOf(ItemsElementName, ItemsChoiceType.LocNum) >= 0;
        }
    }

    public string Address { get { return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.Address); } }

    public string LocNum { get { return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.LocNum); } }

    // Other properties as desired.

    public void SetIndirectLocation(string locNum)
    {
        if (string.IsNullOrEmpty(locNum))
            throw new ArgumentException();
        object[] newItems = new object[] { locNum };
        ItemsChoiceType [] newItemsElementName = new ItemsChoiceType [] { ItemsChoiceType.LocNum };
        this.Items = newItems;
        this.ItemsElementName = newItemsElementName;
    }

    public void SetDirectLocation(string name, string address, string city, string state)
    {
        // In the schema, "City" is mandatory, others are optional.
        if (string.IsNullOrEmpty(city))
            throw new ArgumentException();
        List<object> newItems = new List<object>();
        List<ItemsChoiceType> newItemsElementName = new List<ItemsChoiceType>();
        if (name != null)
        {
            newItems.Add(name);
            newItemsElementName.Add(ItemsChoiceType.Name);
        }
        if (address != null)
        {
            newItems.Add(address);
            newItemsElementName.Add(ItemsChoiceType.Address);
        }
        newItems.Add(city);
        newItemsElementName.Add(ItemsChoiceType.City);
        if (state != null)
        {
            newItems.Add(state);
            newItemsElementName.Add(ItemsChoiceType.State);
        }
        this.Items = newItems.ToArray();
        this.ItemsElementName = newItemsElementName.ToArray();
    }
}

public static class XmlPolymorphicArrayHelper
{
    public static TResult GetItem<TIDentifier, TResult>(TResult[] items, TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier)
    {
        if (itemIdentifiers == null)
        {
            Debug.Assert(items == null);
            return default(TResult);
        }
        Debug.Assert(items.Length == itemIdentifiers.Length);
        var i = Array.IndexOf(itemIdentifiers, itemIdentifier);
        if (i < 0)
            return default(TResult);
        return items[i];
    }
}
public static class XmlPolymorphicArrayHelper
{
    public static TResult GetItem<TIDentifier, TResult>(TResult[] items, TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier)
    {
        if (itemIdentifiers == null)
        {
            return default(TResult);
        }
        var i = Array.IndexOf(itemIdentifiers, itemIdentifier);
        return i < 0 ? default(TResult) : items[i];
    }

    public static void SetItem<TIDentifier, TResult>(ref TResult[] items, ref TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier, TResult value)
    {
        if (itemIdentifiers == null)
        {
            itemIdentifiers = new[] { itemIdentifier };
            items = new[] { value };

            return;
        }

        var i = Array.IndexOf(itemIdentifiers, itemIdentifier);
        if (i < 0)
        {
            var newItemIdentifiers = itemIdentifiers.ToList();
            newItemIdentifiers.Add(itemIdentifier);
            itemIdentifiers = newItemIdentifiers.ToArray();

            var newItems = items.ToList();
            newItems.Add(value);
            items = newItems.ToArray();
        }
        else
        {
            items[i] = value;
        }

    }
}
public partial class LocationType
{
    [XmlIgnore]
    public string Address
    {
        get
        {
            return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.Address);
        }
        set
        {
            XmlPolymorphicArrayHelper.SetItem(ref this.itemsField, ref this.itemsElementNameField, ItemsChoiceType.Address, value);
        }
    }
}