将KeyValuePair列表序列化为XML

本文关键字:XML 序列化 列表 KeyValuePair | 更新日期: 2023-09-27 17:50:48

我正在尝试将对象序列化为XML。下面是我需要的XML格式。

<parameters>
  <parameter>
    <key>Key1</key>
    <value>Value1</value>
    <key>Key2</key>
    <value>Value2</value>
    <key>Key3</key>
    <value>value3</value>
  </parameter>
</parameters>

下面是我创建的模型

[Serializable]
[XmlType("parameters")]
public class parameters
{
    public List<parameter<string,string>> parameter { get; set; }
}
[Serializable]
[XmlType("parameter")]
public class parameter<K,V>
{
    public K key { get; set; }
    public V value { get; set; }
    public parameter() { }
    public parameter(K key, V value)
    {
        this.key = key;
        this.value = value;
    }
}

当我尝试序列化为XML时,我得到以下格式

<parameters>
  <parameter>
    <parameter>
      <key>Key1</key>
      <value>Value1</value>
    </parameter>
    <parameter>
      <key>Key2</key>
      <value>Value2</value>
    </parameter>
    <parameter>
      <key>Key3</key>
      <value>Value3</value>
    </parameter>
  </parameter>
</parameters>

请帮助我解决这个问题

将KeyValuePair列表序列化为XML

XmlSerializer的角度来看,XML的<parameter>元素不是键/值对类的列表,因为每个对在某个包含元素中没有嵌套。相反,它是一个多态列表,其中每个条目可以是类型<key>或类型<value>的元素。因此,处理此问题的最简单方法可能是使用序列化器的内置功能来处理多态类型列表,如下所示:

public abstract class ParameterKeyOrValue<T>
{
    [XmlText]
    public T Text { get; set; }
}
public sealed class ParameterKey<T> : ParameterKeyOrValue<T>
{
}
public sealed class ParameterValue<T> : ParameterKeyOrValue<T>
{
}
[Serializable]
[XmlType("parameters")]
public class parameters
{
    [XmlIgnore]
    public List<parameter<string, string>> parameter { get; set; }
    [XmlArray("parameter")]
    [XmlArrayItem("key", typeof(ParameterKey<string>))]
    [XmlArrayItem("value", typeof(ParameterValue<string>))]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public ParameterKeyOrValue<string>[] XmlParameters
    {
        get
        {
            if (parameter == null)
                return null;
            return parameter.SelectMany(p => new ParameterKeyOrValue<string>[] { new ParameterKey<string> { Text = p.key }, new ParameterValue<string> { Text = p.value } }).ToArray();
        }
        set
        {
            if (value == null)
                parameter = null;
            else
            {
                if (value.Length % 2 != 0)
                    throw new ArgumentException("Unequal number of keys and values");
                var newParameters = value.OfType<ParameterKey<string>>().Zip(value.OfType<ParameterValue<string>>(), (k, v) => new parameter<string, string>(k.Text, v.Text)).ToList();
                // Make sure we got an equal number of keys and values.
                if (newParameters.Count != value.Length / 2)
                    throw new ArgumentException("Unequal number of keys and values");
                parameter = newParameters;
            }
        }
    }
}

[XmlArrayItem("someTypeName", typeof(SomeType))]修饰告诉序列化器,类型为SomeType(本例中为ParameterKey<string>ParameterValue<string>)的数组元素将使用元素名称"someTypeName"(分别为"key""value")进行序列化。

你要么需要让Parameter包含一个键值列表(顺便说一下。net有几个集合为你做这件事,如字典),例如:

public class Parameter<K,V>{
  public Dictionary<K,V> Values {get; set;}
  public Parameter()
  {
     Values = new Dictionary<K,V>();
  }
  public void AddParameter(K key, V value)
  {
     Values.Add(key,value);
  }
  ...Other access methods here
}

或者在parameters中,将其设置为键值列表或字典:

public class Parameters<K,V>{
   public Dictionary<K,V> Parameters {get; set;}
   public Parameters(){
       Parameters = new Dictionary<K,V>();
   }
}

第二个选择显然是最好的,因为第一个只是重新发明。net字典。第一种方法似乎没有任何好处。

这是基本的东西,所以如果你不太了解数组和。net集合,你应该熟悉一下这个领域。

可以使用XmlElementAttribute。ElementName属性来命名你喜欢的参数字典,它应该产生你想要的结果,尽管我会质疑为什么在参数节点内你只想要一个参数节点?