xsd.exe generated c# with multiple elements in an array

后端 未结 2 660
陌清茗
陌清茗 2021-01-02 17:38

I have a set of XML schema files provided to me. I cannot changed the XML as these will be updated on occasion. I am using xsd.exe to convert the schema files to generated c

2条回答
  •  走了就别回头了
    2021-01-02 18:31

    What that schema says is that if some outer type contains an element of type LocationType, one would expect to find inside either

    1) A sub-element , OR

    2) These sub-elements in sequence: ,

    , and .

    Thus the data here is polymorphic, even though it isn't being explicitly modeled as such in the c# classes generated by xsd.exe. This sort of makes sense -- a location might be specified explicitly, or indirectly as a look-up in a table.

    When deserializing a polymorphic sequence like this, XmlSerializer puts each element it finds in the array field corresponding to the elements in the sequence, in this case the array Items. In addition, there should be another corresponding array field identified by the XmlChoiceIdentifierAttribute attribute, in this case ItemsElementName. The entries in this array must needs be in 1-1 correspondence with the Items array. It records the name of the element that was deserialized in each index of the Items array, by way of the ItemsChoiceType enumeration, whose enum names must match the names in the XmlElementAttribute attributes decorating the Items array. This allows the specific choice of polymorphic data to be known.

    Thus, to round out the implementation of your LocationType class, you will need to determine whether a given LocationType is direct or indirect; fetch various properties out; and for each type (direct or indirect), set all required data.

    Here is a prototype of that. (You didn't include the definition for LocationTypeState in your question, so I'm just treating it as a string):

    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 newItems = new List();
            List newItemsElementName = new List();
            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(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];
        }
    }
    
        

    提交回复
    热议问题