Использование универсального словаря поверх wcf: что мне нужно искать?

Предположим, у меня есть служба WCF и метод в контракте.

<ServiceContract()> _
Interface IThingService
'...
  <OperationContract()> _
  Function GetThing(thingId As Guid) As Thing
End Interface

где Thing — обычный класс с обычными свойствами, за исключением одного члена:

Public Class Thing
  ' ...
  Public Property Photos() As Dictionary(Of String, Photo) 
  ' ...
End Class

где Photo — обычный класс с обычными свойствами.

Поэтому я углубился в некоторые документы, такие как эта статья MSDN и < href="http://www.request-response.com/blog/PermaLink,guid,ff5fab81-affb-4b2b-aa67-c80bdfc86cbd.aspx" rel="nofollow noreferrer">этот пост в блоге, и теперь я сбит с толку, если мне нужно многое понять о DataContractSerializer и особенностях того, как служба сериализует свойство Photos.

Нужно ли мне идти туда, или я могу что-то сделать, чтобы WCF на сервере автоматически взаимодействовал с моим клиентом? Мне кажется, что все детали сериализации должны быть в состоянии быть абстрагированы - я просто хочу в конечном итоге в потребляющем клиентском приложении:

Dim foo as Thing = ThingServiceClient.GetThing(someGuid)
Dim myPhotos as Dictionary(Of String, Photo) = foo.Photos

Что мне нужно сделать в моем определении Вещи, чтобы это сработало? Что-нибудь, что мне нужно сделать в другом месте, чтобы заставить это работать? Нужно ли мне беспокоиться о том, чтобы служба оставалась привязанной к DataContractSerializer и не возвращалась к использованию XmlSerializer?


person Patrick Szalapski    schedule 20.08.2009    source источник
comment
О, кстати, этот вопрос вытекает из предыдущего: stackoverflow.com/questions/1294269/   -  person Patrick Szalapski    schedule 20.08.2009
comment
Хотя ответа на этот вопрос пока нет, мы отказались от этого подхода по причинам, не связанным с дизайном, поэтому мне больше не нужен ответ, хотя я хотел бы знать...   -  person Patrick Szalapski    schedule 11.09.2009


Ответы (3)


Я был бы осторожен с предоставлением вам бизнес-объектов непосредственно в контракте WCF (или веб-службе asmx или любой другой внешней точке входа в систему). Это интерфейс, который используют ваши внешние системы, и такой интерфейс должен оставаться постоянным, даже если ваши бизнес-объекты изменяются внутри. В бизнес-объекте также могут быть функции, которые имеют смысл на сервере, но не на клиенте.

Кроме того, вам внезапно нужно изменить свои бизнес-объекты, чтобы они соответствовали выбранной вами коммуникационной технологии, например. вы должны придать своему бизнес-классу атрибуты, атрибуты, которые на самом деле не имеют ничего общего с бизнес-классом.

Я бы создал ThingDTO (DTO = объект передачи данных), содержащий данные для передачи клиенту, и инициализировал бы его данными из экземпляра Thing. Это означает, что если вы считаете, что служба WCF является фасадом системы, то ThingDTO является частью вашего фасадного слоя. И поэтому атрибуты для управления сериализацией WCF могут быть здесь свободно.

Тем не менее, это не то же самое, что имеет смысл в вашем случае. Это всего лишь мой общий взгляд на возврат бизнес-классов из интерфейса WCF.

person Pete    schedule 20.08.2009
comment
Согласен, но я тоже надеялся получить ответ на свой вопрос. Никто не знает? - person Patrick Szalapski; 20.07.2011

Я чуть не убил себя, пытаясь решить эту проблему. В конце концов я все еще жив и с красивым и небольшим кодом. Наслаждайся этим :)

[DataContract, Serializable]
[KnownType("GetKnownTypes")]
public class Dto
{
    [DataMember]
    public Int PropertyA { get; set; }

    [DataMember]
    public String PropertyB { get; set; }

    [DataMember]
    public Dictionary<string, object> MyDictionary { get; set; }

    private static Type[] GetKnownTypes()
    {
        return _myDictionaryValueTypes ?? new Type[] { Typeof(Dictionary<string, object>) };
    }

    private void MyDictionaryValueTypes()
    {
        if (XmlDictionary == null) return;
        _myDictionaryValueTypes = XmlDictionary.Values.Where(value => value != null).Select(value => value.GetType()).ToArray();
    }
}

Единственное, что вам нужно сделать, это вызвать MyDictionaryValueTypes и все.

person Abdel H. Diaz    schedule 02.11.2011

Вам нужно убедиться, что вы украшаете свою «Вещь» атрибутом [DataContract], а все ее члены, которые вы хотите включить в контракт данных, должны иметь атрибут [DataMember]. То же самое касается вашего класса «Фото».

Пока вам не приходится иметь дело с полиморфизмом (наследованием) и/или пользовательскими коллекциями, это действительно так. Об остальном позаботится за вас среда выполнения WCF.

Марк

person marc_s    schedule 20.08.2009
comment
У меня нет атрибута DataContract ни в одном из моих классов, и как только я добавляю его, я получаю следующее исключение. Любая идея, что я делаю неправильно? {Произошла ошибка при получении ответа HTTP на localhost/MyService/MyService.svc/…. Это может быть связано с тем, что привязка конечной точки службы не использует протокол HTTP. Это также может быть связано с прерыванием сервером контекста HTTP-запроса (возможно, из-за закрытия службы). Дополнительные сведения см. в журналах сервера.} - person Patrick Szalapski; 20.08.2009
comment
Какую привязку используете? А что вам говорят логи сервера? - person marc_s; 20.08.2009