Как реализовать унаследованный словарь над WCF - PullRequest
7 голосов
/ 06 ноября 2008

Я пытаюсь реализовать словарь для использования с WCF. Мои требования:

  • актуально (приватная переменная или база класс) тип, эквивалентный Словарь
  • Comparer = System.StringComparer.InvariantCultureIgnoreCase
  • Пользовательский (переопределить / новый) Добавить (ключ, значение) метод (чтобы включить валидация).
  • Переопределить ToString ()
  • Использование одного и того же типа на клиенте и хосте

Я пытался использовать этот класс в общем проекте, совместно используемом WCF-хостом и клиентскими проектами:

[Serializable]
public class MyDictionary : Dictionary<string, object>
{
  public MyDictionary()
    : base(System.StringComparer.InvariantCultureIgnoreCase)
  { }

  public new void Add(string key, object value)
  { /* blah */ }

  public override string ToString()
  { /* blah */ }
}

[DataContract]
[KnownType(typeof(MyDictionary))]
[KnownType(typeof(object[]))]
[KnownType(typeof(double[]))]
[KnownType(typeof(string[]))]
[KnownType(typeof(DateTime[]))]
public class ResultClass
{
  public object Value{ get; set; }
  /* More properties */
}
public class ParmData
{
  public object Value{ get; set; }
  /* More properties */
}
[DataContract]
[KnownType(typeof(MyDictionary))]
[KnownType(typeof(object[]))]
[KnownType(typeof(double[]))]
[KnownType(typeof(string[]))]
[KnownType(typeof(DateTime[]))]
public class ParameterClass
{
  public List<ParmData> Data{ get; set; }
  /* More properties */
}

[OperationContract]
ResultClass DoSomething(ParameterClass args);

Результаты:

  • Когда я передаю MyDictionary в качестве одного из элементов ParameterClass.Data.Value, я получаю отсутствующее исключение KnownType.
  • Я могу безопасно вернуть MyDictionary в ResultClass, но это больше не мой тип. Это просто словарь, и его нельзя преобразовать в MyDictionary. Кроме того, сравнивающий = System.Collections.Generic.GenericEqualityComparer<string>, а не регистр без учета регистра, который я ищу.

Помощь, о которой я прошу, состоит в том, чтобы исправить мою неудачную попытку или полностью изменить мои заявленные требования. Любое решение не должно включать копирование одного словаря в другой.

Спасибо

Ответы [ 4 ]

10 голосов
/ 06 ноября 2008

Добавление CollectionDataContract в класс Dictionary:

Для получения дополнительной информации об использовании контрактов сбора данных для реализации словарей, перейдите по этой ссылке:

http://msdn.microsoft.com/en-us/library/aa347850.aspx

1 голос
/ 18 февраля 2009

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

  1. Убедитесь, что вы добавили [CollectionDataContract] в свою коллекцию
  2. Добавить ссылку на службу через VS, как вы обычно делаете
  3. Разверните ссылку на сервис и найдите файл Reference.svcmap
  4. Под узлом опций клиента вы увидите

Замените его следующим xml.



  1. Щелкните правой кнопкой мыши Справочник по услугам и нажмите Обновить. Он больше не должен генерировать этот прокси-класс и позволит вам использовать ваш общий класс.
1 голос
/ 07 ноября 2008
  • Используйте атрибут CollectionDataContract, как предложено Джезеллом
  • Сгенерируйте ссылочный (прокси) код вручную с помощью SvcUtil, используя параметр / collectionType. Этот параметр не поддерживается справочным интерфейсом службы vs2008.

Источник: Совместное использование типа коллекции WCF

1 голос
/ 06 ноября 2008

Преамбула: обратите внимание, что добавление «нового» * ​​1001 * не останавливает людей, называющих старую Add простым кастом. Кроме того, с точки зрения «mex», это очень расплывчатый контракт на данные - должен ли он быть таким открытым? (много object и т.д ...)

Во-первых: вы не пропустили несколько маркеров [DataContract] / [DataMember] там? В частности:

  • ResultClass.Value
  • ParamData
  • ParamData.Value
  • ParameterClass.Data

Можете ли вы уточнить точно , какую версию .NET вы используете? DataContractSerializer и т. Д. Были подправлены через пакеты обновления. С установленным 3.5 SP1 (единственное, что мне нужно передать) он по крайней мере сериализуется и десериализуется через DataContractSerializer (без стека WCF), и вызывается правильный метод Add.

Можете ли вы проверить, работает ли следующее с вашей локальной версией? (у меня работает с 3.5 SP1 и с отсутствующими атрибутами) [сначала вывод]:

1
MyDictionary
abc=123
def=ghi

Код:

        // or long-hand in C# 2.0
        ParameterClass pc = new ParameterClass {
            Data = new List<ParmData> { new ParmData {
                Value = new MyDictionary  {
                    {"abc",123},
                    {"def","ghi"}
                }}}};
        DataContractSerializer dcs = new DataContractSerializer(pc.GetType());
        string xml;
        using(StringWriter sw = new StringWriter())
        using(XmlWriter xw = XmlWriter.Create(sw)) {
            dcs.WriteObject(xw, pc);
            xw.Close();
            xml = sw.ToString();
        }
        using(StringReader sr = new StringReader(xml)) {
            ParameterClass clone = (ParameterClass)dcs.ReadObject(XmlReader.Create(sr));
            Console.WriteLine(clone.Data.Count);
            Console.WriteLine(clone.Data[0].Value.GetType().Name);
            MyDictionary d = (MyDictionary)clone.Data[0].Value;
            foreach (KeyValuePair<string, object> pair in d)
            {
                Console.WriteLine("{0}={1}", pair.Key, pair.Value);
            }
        }

Очевидно, это просто тестирует DataContractSerializer (без всего стека WCF), но, похоже, работает ... так: работает ли тот же код с вашей локальной версией .NET? Если нет, то стоит ли устанавливать последний пакет обновления 3.0? (в идеале через установку 3.5 SP1).

Для получения информации я получаю xml:

<?xml version="1.0" encoding="utf-16"?><ParameterClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/"><Data><ParmData><Value xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:type="d4p1:ArrayOfKeyValueOfstringanyType"><d4p1:KeyValueOfstringanyType><d4p1:Key>abc</d4p1:Key><d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:int">123</d4p1:Value></d4p1:KeyValueOfstringanyType><d4p1:KeyValueOfstringanyType><d4p1:Key>def</d4p1:Key><d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:string">ghi</d4p1:Value></d4p1:KeyValueOfstringanyType></Value></ParmData></Data></ParameterClass>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...