如何在Web服务中返回通用字典

时间:2009-03-24 20:08:09

标签: c# generics

我希望C#中的Web服务根据搜索返回一个Dictionary:

Dictionary<int, string> GetValues(string search) {}

Web服务编译正常,但是,当我尝试引用它时,我收到以下错误: “不支持,因为它实现了IDictionary。”

¿我能做些什么来使这个工作?,任何不涉及返回DataTable的想法?

5 个答案:

答案 0 :(得分:25)

没有“默认”方式来获取Dictionary并将其转换为XML。您必须选择一种方式,并且您的Web服务的客户在使用您的服务时必须注意相同的方式。如果客户端和服务器都是.NET,那么您可以简单地使用相同的代码在两端将字典序列化和反序列化为XML。

有代码可以执行此操作in this blog post。此代码使用Dictionary的键和值的默认序列化,当您具有非字符串类型时,这非常有用。代码使用继承来做它的事情(你必须使用该子类来存储你的值)。您也可以使用包装类型方法,如this article中的最后一项所述,但请注意该文章中的代码只使用ToString,因此您应该将它与第一篇文章结合使用。

因为我同意Joel关于StackOverflow是所有内容的规范来源,所以下面是第一个链接的代码副本。如果您发现任何错误,请编辑此答案!

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    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();
    }

    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
}

答案 1 :(得分:7)

创建一个类型MyKeyValuePair<K,V>,并返回从字典中复制的List<MyKeyValuePair<int,string>>

答案 2 :(得分:5)

This article有一个序列化IDictionaries的方法。寻找“我注意到默认情况下XmlSerializer不会序列化实现IDictionary的对象。有什么方法可以解决这个问题吗?”在页面的下方约2/3。

答案 3 :(得分:4)

我使用这个util类来序列化词典,也许它对你有用

using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace Utils {
    ///<summary>
    ///</summary>
    public class SerializableDictionary : IXmlSerializable {
        private readonly IDictionary<int, string> dic;
        public DiccionarioSerializable() {
            dic = new Dictionary<int, string>();
        }
        public SerializableDictionary(IDictionary<int, string> dic) {
            this.dic = dic;
        }
        public IDictionary<int, string> Dictionary {
            get { return dic; }
        }
        public XmlSchema GetSchema() {
            return null;
        }
        public void WriteXml(XmlWriter w) {
            w.WriteStartElement("dictionary");
            foreach (int key in dic.Keys) {
                string val = dic[key];
                w.WriteStartElement("item");
                w.WriteElementString("key", key.ToString());
                w.WriteElementString("value", val);
                w.WriteEndElement();
            }
            w.WriteEndElement();
        }
        public void ReadXml(XmlReader r) {
            if (r.Name != "dictionary") r.Read(); // move past container
            r.ReadStartElement("dictionary");
            while (r.NodeType != XmlNodeType.EndElement) {
                r.ReadStartElement("item");
                string key = r.ReadElementString("key");
                string value = r.ReadElementString("value");
                r.ReadEndElement();
                r.MoveToContent();
                dic.Add(Convert.ToInt32(key), value);
            }
        }
    }
}

答案 4 :(得分:2)

使用SerializableDictionary的此解决方案效果很好,但在工作期间您可以获得

cannot convert from 'SerializableDictionary<string,string>' to 'System.Data.DataSet'

错误。在这种情况下你应该去Project-&gt;显示所有文件,然后在Web服务的Reference.cs文件中将参数类型编辑为SerializableDictionary。这是一个官方的微软bug,在这里更详细:

http://support.microsoft.com/kb/815131