今天在实现一个WebService方法时想放回一个Dictionary,编译通过,但是运行时报“is not supported because it implements IDictionary.”,这时由于Dictionary不能进行xml序列化引起的,因此我们要实现一个继承IXmlSerializable序列化接口的类才可以,代码如下:
[XmlRoot("SerializableDictionary")]
public class SerializableDictionary
: Dictionary, IXmlSerializable
{
#region 构造函数
public SerializableDictionary()
: base()
{
}
public SerializableDictionary(IDictionary dictionary)
: base(dictionary)
{
}
#endregion
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
///
/// 从对象的 XML 表示形式生成该对象
///
///
public void ReadXml(System.Xml.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 != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
/**/
///
/// 将对象转换为其 XML 表示形式
///
///
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
}
然后在要返回Dictionary的方法里使用SerializableDictionary构造方法,像这样:
public SerializableDictionaryFunc() { Dictionary a = new Dictionary (); a.Add(1,"a"); a.Add(2,"b"); a.Add(3,"c"); return new SerializableDictionary (a); }
以为这样就大功告成了,但是在客户端引用的时候又出现了问题,看了一下Func()的返回结果居然是DataSet,然后费了好大的功夫想把DataSet转化一下,发现根本转不过来,于是又求助了万能的谷歌,在 栈溢出了 上面找到了下面的方法:
[amazon_link asins=’B01LW72R2M,B00P8VZ8T4,B015316YQE’ template=’CopyOf-ProductGrid’ store=’boyd-23′ marketplace=’CN’ link_id=”]
This solution with SerializableDictionary works great, but during work You can get cannot convert from 'SerializableDictionary' to 'System.Data.DataSet' error. In this case You should go Project-> Show all files, and then edit argument type to SerializableDictionary in Reference.cs file of web service. It's an official microsoft bug
上面说明了这是一个微软官方的bug,需要手动把Reference.cs里面方法的返回类型DataSet手动修改成自定义的类型,例如:
原代码
public System.Data.DataSet Func() {
object[] results = this.Invoke("Func", new object[0]);
return ((System.Data.DataSet)(results[0]));
}
把上面代码中的两处System.Data.DataSet改成Dictionary
public Dictionary Func() {
object[] results = this.Invoke("Func", new object[0]);
return ((Dictionary)(results[0]));
}
参考连接:
http://social.msdn.microsoft.com/Forums/vstudio/zh-CN/110fc8c1-99a2-4bc5-a1ac-1bee2fd3a922/dictionaryintstring?forum=visualcshartzhchs
http://support.microsoft.com/kb/815131#top