将 KeyValuePair 列表序列化为 XML

serializing a list of KeyValuePair to XML

我正在尝试将对象序列化为 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>

请帮我解决这个问题。

您要么需要使参数包含键值列表(顺便说一句,.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
}

或者在参数中将其设为键值列表或字典:

public class Parameters<K,V>{

   public Dictionary<K,V> Parameters {get; set;}

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

第二种选择显然是最好的,因为第一种只是重新发明了 .net 词典。第一个好像没什么用。

这是生活必需品,所以如果您不真正理解数组和 .net 集合,您应该熟悉这个领域。搜索堆栈溢出将为您提供所需的一切。

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

XmlSerializer 的角度来看,XML 的 <parameter> 元素不是 key/value 对 类 的列表,因为在某些包含元素中没有每对嵌套。相反,它是一个 polymorphic list,其中每个条目可以是类型 <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"。)