简体   繁体   English

如何在 WebService 中返回通用字典

[英]How to Return Generic Dictionary in a WebService

I want a Web Service in C# that returns a Dictionary, according to a search:根据搜索,我想要 C# 中的 Web 服务返回一个字典:

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

The Web Service compiles fine, however, when i try to reference it, i get the following error: "is not supported because it implements IDictionary." Web 服务编译良好,但是,当我尝试引用它时,我收到以下错误:“不支持,因为它实现了 IDictionary。”

¿What can I do in order to get this working?, any ideas not involving return a DataTable? ¿ 我能做些什么才能使它正常工作?任何不涉及返回 DataTable 的想法?

There's no "default" way to take a Dictionary and turn it into XML.没有“默认”方式来获取字典并将其转换为 XML。 You have to pick a way, and your web service's clients will have to be aware of that same way when they are using your service.您必须选择一种方式,并且您的 web 服务的客户在使用您的服务时也必须注意同样的方式。 If both client and server are .NET, then you can simply use the same code to serialize and deserialize Dictionaries to XML on both ends.如果客户端和服务器都是.NET,那么你可以简单地使用相同的代码在两端将字典序列化和反序列化为XML。

There's code to do this in this blog post .此博客文章中有执行此操作的代码。 This code uses the default serialization for the keys and values of the Dictionary, which is useful when you have non-string types for either.此代码使用字典的键和值的默认序列化,这在您有非字符串类型时很有用。 The code uses inheritance to do its thing (you have to use that subclass to store your values).该代码使用 inheritance 来完成它的工作(您必须使用该子类来存储您的值)。 You could also use a wrapper-type approach as done in the last item in this article , but note that the code in that article just uses ToString, so you should combine it with the first article.您还可以使用本文最后一项中所做的包装类型方法,但请注意,该文章中的代码仅使用 ToString,因此您应该将其与第一篇文章结合使用。

Because I agree with Joel about StackOverflow being the canonical source for everything, below is a copy of the code from the first link.因为我同意 Joel 关于 StackOverflow 是所有内容的规范来源的观点,所以下面是第一个链接中的代码副本。 If you notice any bugs, edit this answer!如果您发现任何错误,请编辑此答案!

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
}

Create a type MyKeyValuePair<K,V> , and return a List<MyKeyValuePair<int,string>> , copied from the dictionary.创建一个类型MyKeyValuePair<K,V> ,并返回一个List<MyKeyValuePair<int,string>> ,从字典中复制。

This article has a method to serialize IDictionaries.本文有一个序列化 IDictionaries 的方法。 Look for " I've noticed that XmlSerializer won't serialize objects that implement IDictionary by default. Is there any way around this?"寻找“我注意到 XmlSerializer 默认不会序列化实现 IDictionary 的对象。有什么办法解决这个问题吗?” about 2/3 the way down the page.大约在页面下方的 2/3 处。

I use this util class for serializing dictionaries, maybe it can be useful for you我使用这个工具 class 来序列化字典,也许它对你有用

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

This solution with SerializableDictionary works great, but during work You can get这个带有 SerializableDictionary 的解决方案效果很好,但是在工作期间你可以得到

cannot convert from 'SerializableDictionary<string,string>' 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.在这种情况下,您应该 go Project-> Show all files,然后在 web 服务的 Reference.cs 文件中将参数类型编辑为 SerializableDictionary。 It's an official microsoft bug, more detailed here:这是一个官方的微软错误,在这里更详细:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM