该模式所说的是,如果某个外部类型包含类型的元素LocationType
,人们会期望在里面找到either
1) 子元素<LocNum>
, OR
2) 这些子元素按顺序排列:<Name>
, <Address>
, <City>
and <State>
.
因此,这里的数据是多态的,即使它没有在 xsd.exe 生成的 C# 类中显式建模。这是有道理的——可以显式指定位置,也可以间接指定为表中的查找。
当反序列化这样的多态序列时,XmlSerializer
将它找到的每个元素放入与序列中的元素相对应的数组字段中,在本例中为数组Items
。此外,还应该有另一个对应的数组字段,由XmlChoiceIdentifierAttribute属性,在本例中ItemsElementName
。该数组中的条目必须与Items
大批。它记录了在每个索引中反序列化的元素的名称Items
数组,通过ItemsChoiceType
枚举,其枚举名称必须与中的名称匹配XmlElementAttribute装饰属性Items
大批。这使得多态性数据的具体选择是已知的。
因此,为了完善您的实施LocationType
类,您需要确定是否给定LocationType
是直接的还是间接的;取出各种属性;并为每种类型(直接或间接)设置所有必需的数据。
这是一个原型。 (您没有包含以下定义LocationTypeState
在你的问题中,所以我只是将它视为一个字符串):
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];
}
}