今天在实现一个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 DictionaryFunc() { 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