我使用this blog entry中定義的SerializableDictionary
來存儲<string, object>
數據並將它傳遞給WCF服務或從其傳遞。如果我使用值類型作爲值,這可以很好地工作,因爲它們可以很容易變成object
s。不過,如果我使用類似使用對象串行器對列表進行序列化
new List<int>() { 5, 10 }
,我得到一個異常:
類型System.Collections.Generic.List`1 [[System.Int32,mscorlib程序,版本= 4.0.0.0,文化= neutral,PublicKeyToken = b77a5c561934e089]]可能不會在此上下文中使用。
根據討論here,我應該使用value.GetType()
初始化XmlSerializer
;然而,雖然這讓我序列化,我不知道如何反序列化一般回到我的SerializableDictionary
。
我不確定是否有一種方法可以在乾淨地更改這個同時仍允許<string, object>
作爲我的類型參數 - 我可以將該值序列化爲二進制而不是XML,並以此方式傳輸(相同的代碼是序列化和反序列化,所以我不關心互操作性),但是我想盡可能地使用XML。
編輯
完整的代碼示例:
XmlSerializer serializer = new XmlSerializer(typeof(SerializableDictionary<string, object>));
SerializableDictionary<string, object> dic = new SerializableDictionary<string, object>();
dic["test"] = new List<int>() { 5, 10 };
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
serializer.Serialize(writer, dic);
string ser = sb.ToString();
SOLUTION
由於尼科Schertler給我正確的答案。我在這裏發佈我的最終代碼以防萬一需要。這與第一個鏈接中的原始代碼向後兼容,所以任何被該代碼序列化的內容都可以通過下面的方式進行反序列化。
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
#region " IXmlSerializable Members "
#region " WriteXml "
public void WriteXml(XmlWriter writer)
{
// Base types
string baseKeyType = typeof(TKey).AssemblyQualifiedName;
string baseValueType = typeof(TValue).AssemblyQualifiedName;
writer.WriteAttributeString("keyType", baseKeyType);
writer.WriteAttributeString("valueType", baseValueType);
foreach (TKey key in this.Keys)
{
// Start
writer.WriteStartElement("item");
// Key
Type keyType = key.GetType();
XmlSerializer keySerializer = GetTypeSerializer(keyType.AssemblyQualifiedName);
writer.WriteStartElement("key");
if (keyType != typeof(TKey)) { writer.WriteAttributeString("type", keyType.AssemblyQualifiedName); }
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
// Value
TValue value = this[key];
Type valueType = value.GetType();
XmlSerializer valueSerializer = GetTypeSerializer(valueType.AssemblyQualifiedName);
writer.WriteStartElement("value");
if (valueType != typeof(TValue)) { writer.WriteAttributeString("type", valueType.AssemblyQualifiedName); }
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
// End
writer.WriteEndElement();
}
}
#endregion
#region " ReadXml "
public void ReadXml(XmlReader reader)
{
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
{
return;
}
// Base types
string baseKeyType = typeof(TKey).AssemblyQualifiedName;
string baseValueType = typeof(TValue).AssemblyQualifiedName;
while (reader.NodeType != XmlNodeType.EndElement)
{
// Start
reader.ReadStartElement("item");
// Key
XmlSerializer keySerializer = GetTypeSerializer(reader["type"] ?? baseKeyType);
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
// Value
XmlSerializer valueSerializer = GetTypeSerializer(reader["type"] ?? baseValueType);
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
// Store
this.Add(key, value);
// End
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
#endregion
#region " GetSchema "
public XmlSchema GetSchema()
{
return null;
}
#endregion
#endregion
#region " GetTypeSerializer "
private static readonly Dictionary<string, XmlSerializer> _serializers = new Dictionary<string, XmlSerializer>();
private static readonly object _deadbolt = new object();
private XmlSerializer GetTypeSerializer(string type)
{
if (!_serializers.ContainsKey(type))
{
lock (_deadbolt)
{
if (!_serializers.ContainsKey(type))
{
_serializers.Add(type, new XmlSerializer(Type.GetType(type)));
}
}
}
return _serializers[type];
}
#endregion
}
我只是寫出來的類型,如果它是不是在爲了保持XML下來的長度基本類型不同,和我保持的XmlSerializer
個靜態列表,以防止intantiating他們到處都是。爲了能夠防止在每個節點上寫出類型,我必須在開始時寫出所提供的類型。
zimdanen是你試圖通過/分配數組.. int?是否有你在這裏顯示的錯字'新列表(){5,10}'哪裏是'=' –
MethodMan
2013-02-25 17:41:29
@DJKRAZE:我試圖使用SerializableDictionary <字符串對象序列化一個'List' >'。我將添加一個完整的代碼段來演示這個問題。 –
zimdanen
2013-02-25 17:46:59