我正在寻找可以包含在Web服务中的键/值对对象。
我尝试使用.NET的System.Collections.Generic.KeyValuePair<>类,但是它无法在Web服务中正确序列化。在Web服务中,键和值属性不会被序列化,从而使该类无用,除非有人知道解决此问题的方法。
在这种情况下还有其他通用类吗?
我将使用.NET的System.Web.UI.Pair类,但是它使用Object作为其类型。如果仅出于类型安全的考虑,最好使用Generic类。
只需定义一个结构体/类。
1 2 3 4 5 6
| [Serializable]
public struct KeyValuePair<K,V>
{
public K Key {get;set;}
public V Value {get;set;}
} |
我不认为这是因为Dictionary<>本身不是XML可序列化的,当我需要通过Web服务发送字典对象时,我最终自己包装了Dictionary<>对象并添加了对。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| /// <summary>
/// Represents an XML serializable collection of keys and values.
/// </summary>
/// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
/// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
#region Constants
/// <summary>
/// The default XML tag name for an item.
/// </summary>
private const string DEFAULT_ITEM_TAG ="Item";
/// <summary>
/// The default XML tag name for a key.
/// </summary>
private const string DEFAULT_KEY_TAG ="Key";
/// <summary>
/// The default XML tag name for a value.
/// </summary>
private const string DEFAULT_VALUE_TAG ="Value";
#endregion
#region Protected Properties
/// <summary>
/// Gets the XML tag name for an item.
/// </summary>
protected virtual string ItemTagName
{
get
{
return DEFAULT_ITEM_TAG;
}
}
/// <summary>
/// Gets the XML tag name for a key.
/// </summary>
protected virtual string KeyTagName
{
get
{
return DEFAULT_KEY_TAG;
}
}
/// <summary>
/// Gets the XML tag name for a value.
/// </summary>
protected virtual string ValueTagName
{
get
{
return DEFAULT_VALUE_TAG;
}
}
#endregion
#region Public Methods
/// <summary>
/// Gets the XML schema for the XML serialization.
/// </summary>
/// <returns>An XML schema for the serialized object.</returns>
public XmlSchema GetSchema()
{
return null;
}
/// <summary>
/// Deserializes the object from XML.
/// </summary>
/// <param name="reader">The XML representation of the object.</param>
public void ReadXml(XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
{
return;
}
while (reader.NodeType != XmlNodeType.EndElement)
{
reader.ReadStartElement(ItemTagName);
reader.ReadStartElement(KeyTagName);
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement(ValueTagName);
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
/// <summary>
/// Serializes this instance to XML.
/// </summary>
/// <param name="writer">The writer to serialize to.</param>
public void WriteXml(XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement(ItemTagName);
writer.WriteStartElement(KeyTagName);
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement(ValueTagName);
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
} |
您将在此MSDN博客文章中找到无法对KeyValuePairs进行序列化的原因
Struct答案是最简单的解决方案,但不是唯一的解决方案。一个"更好"的解决方案是编写一个可序列化的Custom KeyValurPair类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| [Serializable]
public class SerializableKeyValuePair<TKey, TValue>
{
public SerializableKeyValuePair()
{
}
public SerializableKeyValuePair(TKey key, TValue value)
{
Key = key;
Value = value;
}
public TKey Key { get; set; }
public TValue Value { get; set; }
} |
在4.0框架中,还添加了可序列化和等价的Tuple系列类。您可以使用Tuple.Create(a, b)或new Tuple<T1, T2>(a, b)。
DataTable是我最喜欢的用于(仅)包装要序列化为JSON的数据的集合,因为它很容易扩展,而无需额外的struct
使用DataContractSerializer,因为它可以处理键值对。
1 2 3 4 5 6 7 8 9 10 11
| public static string GetXMLStringFromDataContract(object contractEntity)
{
using (System.IO.MemoryStream writer = new System.IO.MemoryStream())
{
var dataContractSerializer = new DataContractSerializer(contractEntity.GetType());
dataContractSerializer.WriteObject(writer, contractEntity);
writer.Position = 0;
var streamReader = new System.IO.StreamReader(writer);
return streamReader.ReadToEnd();
}
} |
XmlSerializer不适用于"字典"。哦,KeyValuePairs也有问题
http://www.codeproject.com/Tips/314447/XmlSerializer-doesnt-work-with-Dictionaries-Oh-and
KeyedCollection是一种字典类型,可以直接序列化为xml,而无需任何废话。唯一的问题是,您必须通过以下方式访问值:coll [" key"]。Value;
您可以使用Tuple<string,object>
有关Tuple用法的更多详细信息,请参见此:在C#4.0中使用Tuple。