Как вернуть универсальный словарь в веб-сервис - PullRequest
27 голосов
/ 24 марта 2009

Мне нужен веб-сервис на C #, который возвращает словарь в соответствии с поиском:

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

Веб-служба компилируется нормально, однако, когда я пытаюсь ссылаться на нее, я получаю следующую ошибку: "не поддерживается, потому что он реализует IDictionary."

¿Что я могу сделать, чтобы заставить это работать? Какие идеи, не связанные с возвращением DataTable?

Ответы [ 5 ]

25 голосов
/ 15 августа 2009

Не существует способа «по умолчанию» взять словарь и превратить его в XML. Вы должны выбрать способ, и клиенты вашего веб-сервиса должны будут знать об этом точно так же, когда они используют ваш сервис. Если и клиент, и сервер являются .NET, то вы можете просто использовать один и тот же код для сериализации и десериализации словарей в XML на обоих концах.

В этом сообщении для блога есть код для этого . Этот код использует сериализацию по умолчанию для ключей и значений словаря, что полезно, когда у вас есть не строковые типы для обоих. Код использует наследование, чтобы делать свое дело (вы должны использовать этот подкласс для хранения ваших значений). Вы также можете использовать подход типа оболочки, как это было сделано в последнем пункте этой статьи , но обратите внимание, что код в этой статье просто использует ToString, поэтому вы должны объединить его с первой статьей.

Поскольку я согласен с Джоэлом в том, что 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
}
7 голосов
/ 24 марта 2009

Создайте тип MyKeyValuePair<K,V> и верните List<MyKeyValuePair<int,string>>, скопированный из словаря.

5 голосов
/ 24 марта 2009

В этой статье есть метод сериализации идентификаторов. Поищите: «Я заметил, что XmlSerializer не будет сериализовать объекты, которые реализуют IDictionary по умолчанию. около 2/3 пути вниз по странице.

4 голосов
/ 30 марта 2009

Я использую этот класс утилит для сериализации словарей, может быть, он вам пригодится

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);
            }
        }
    }
}
2 голосов
/ 23 февраля 2012

Это решение с SerializableDictionary прекрасно работает, но во время работы вы можете получить

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

ошибка. В этом случае вам нужно перейти Project-> Show all files, а затем отредактировать тип аргумента в SerializableDictionary в файле Reference.cs веб-сервиса. Это официальная ошибка Microsoft, более подробно здесь:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...