如何序列化列表< T> c#中的属性,但未在XML序列化中显示其类型

如何序列化列表< T> c#中的属性,但未在XML序列化中显示其类型

问题描述:

我有一个需要以XML序列化的类.下面是示例:

I have a class for which I need to serialize it in XML. Below is the example:

public class StringArray
{        
    public List<string> Days { get; set; }

    public StringArray()
    {
        List<string> s = new List<string>();
        s.Add("Monday");
        s.Add("Tuesday");
        s.Add("Wed");           
        Days = s;
    }
}

当我以XML格式序列化它时,结果是:

When I Serialize it in XML format then result is:

 <StringArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <Days>
     <string>Monday</string>
     <string>Tuesday</string>
     <string>Wed</string>
   </Days>
 </StringArray>

但是,我需要如下所示的结果:

However, I need result like below:

 <StringArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <Days>             
         <Monday />
         <Tuesday />
         <Wed />                 
  </Days>
</StringArray>

实际上我不想显示列表项的类型.

Actually I do not want to show the type of list item.

请注意,可能的字符串集是固定的.我也尝试为此使用enum,但是XML显示的是enum类型名称而不是'string',这不能解决问题.

Note that the set of possible strings is fixed. I also tried using an enum for this, however the XML shows the enum type name instead of 'string' which doesn't solve the problem.

由于只有固定的一组可能的字符串值,因此您的架构对应于无限制的选择元素,其中可能的元素名称与可能的字符串值相对应.

Since you have only a fixed set of possible string values, your schema corresponds to an unbounded sequence of choice elements, where the possible element names correspond to the possible string values.

这可以通过以下方式建模:将string替换为适当的enum,然后使用选择元素绑定支持支持内置在中,这需要应用 DTO .

This can be modeled by replacing the string with some appropriate enum, then making use of the Choice Element Binding Support support built in to XmlSerializer, which requires application of XmlChoiceIdentifierAttribute along with the use of an appropriate serialization surrogate DTO.

首先,定义一个与可能的字符串值相对应的enum:

First, define an enum that corresponds to the possible string values:

public enum Day
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

接下来,定义以下DTO,这些DTO将取代您的List<Day>:

Next, define the following DTO which will be serialized in place of your List<Day>:

public class DayListDTO
{
    [XmlIgnore]
    public Day [] Days { get; set; }

    [XmlChoiceIdentifier(nameof(DayListDTO.Days))]
    [XmlElement(nameof(Day.Monday), typeof(object))]
    [XmlElement(nameof(Day.Tuesday), typeof(object))]
    [XmlElement(nameof(Day.Wednesday), typeof(object))]
    [XmlElement(nameof(Day.Thursday), typeof(object))]
    [XmlElement(nameof(Day.Friday), typeof(object))]
    [XmlElement(nameof(Day.Saturday), typeof(object))]
    [XmlElement(nameof(Day.Sunday), typeof(object))]
    public object[] DaysObjects
    {
        get
        {
            return Days == null ? null : Enumerable.Repeat(new object(), Days.Length).ToArray();
        }
        set
        {
            // Do nothing
        }
    }

    public static implicit operator DayListDTO(List<Day> list)
    {
        return list == null ? null : new DayListDTO { Days = list.ToArray() };
    }

    public static implicit operator List<Day>(DayListDTO dayList)
    {
        return dayList?.Days?.ToList() ?? new List<Day>();
    }
}

最后,通过将代理属性添加到包含类中来利用DTO,如下所示:

Finally, make use of the DTO by adding surrogate properties to containing classes as follows:

public class StringArray
{
    [XmlIgnore]
    public List<Day> Days { get; set; }

    [XmlElement("Days")]
    public DayListDTO XmlDaysSurrogate { get { return Days; } set { Days = value; } }
}

序列化后会生成以下XML:

Which, when serialized, generates the following XML:

<StringArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Days>
    <Monday />
    <Tuesday />
    <Wednesday />
  </Days>
</StringArray>

注意:

  • 要在数组上正确使用XmlChoiceIdentifier,包含的DTO类型必须具有两个数组成员:

  • To use XmlChoiceIdentifier correctly with an array, your containing DTO type must have two array members:

  1. 一个数组,记录选择元素的内容,此处为DayListDTO.DaysObjects;
  2. 一个数组,该数组记录选择元素的名称(此处为DayListDTO.Days),与第一个数组成1-1对应.
  1. One array that records the contents of the choice elements, here DayListDTO.DaysObjects;
  2. One array that records the names of the choice elements, here DayListDTO.Days, in 1-1 correspondence with the first array.


由于与您的枚举列表相对应的元素根本不包含任何内容,因此将为第一个数组返回object个项目的虚拟数组.

使用XmlChoiceIdentifier保证 xsd.exe 会正确地指示正确命名的选择元素的无限范围.其他解决方案(例如,通过 IXmlSerializable List<Day>的某些子类上实现自定义序列化)没有这种优势.

Using XmlChoiceIdentifier guarantees that the schema which xsd.exe auto-generates for your types will correctly indicate an unbounded sequence of correctly-named choice elements. Other solutions such as implementing custom serialization via IXmlSerializable on some subclass of List<Day> do not have this advantage.

工作示例小提琴此处.