Protobuf.net Список десериализации WCF <T> - PullRequest
4 голосов
/ 28 октября 2010

Я пытаюсь использовать WCF с protobuf-net r.282

ОК.Я отмечаю свои контракты атрибутом ProtoBehavior

    [OperationContract,ProtoBehavior]
    [FaultContract(typeof(ServiceFaultException))]
    Dictionary<ActivityCategoryDTO, SalesTemplateDTO> GetSalesTemplates();

    [OperationContract, ProtoBehavior]
    [FaultContract(typeof(ServiceFaultException))]
    List<ActivityCategoryDTO> GetActivities();

Далее, - DTO:

    [DataContract]
    [Serializable]
    [ProtoContract]
    public class ActivityCategoryDTO
    {
        [DataMember]
        [ProtoMember(1)]
        public int Id { get; set; }
        [DataMember]
        [ProtoMember(2)]
        public string Guid { get; set; }
        [DataMember]
        [ProtoMember(3)]
        public string Name { get; set; }
    }

Я пытаюсь использовать эту услугу у клиента.Когда я вызываю GetSalesTemplates - все в порядке.У меня есть успешный десериализованный словарь, но когда я вызываю GetActivities, я получаю ноль на клиенте.Через фидлер я вижу, что данные успешно передаются, поэтому я думаю, что это проблема десериализатора.

Что не так?Как я могу получить список на клиенте?

РЕДАКТИРОВАТЬ

Кажется, у меня есть проблемы со всеми списками:)

[DataContract]
[Serializable]
[ProtoContract]
public class SalesTemplateDTO
{
    [ProtoMember(1)]
    [DataMember]
    public string Name { get; set; }
    [ProtoMember(2)]
    public List<FieldTemplateDTO> Fields;
}

Доклиент только с именем, список полей снова нулевой.Хотя все данные тоже передаются.

Ответы [ 2 ]

4 голосов
/ 13 ноября 2010

OK; Я воспроизвел, и это на самом деле похоже на то, что IDE / svcutil отказывается повторно использовать контракт на обслуживание (интерфейс) из вашей сборки DTO, даже если он повторно использует контракты на данные (классы). В сгенерированном мексом сервисном контракте (интерфейсе) отсутствуют необходимые дополнительные атрибуты, поэтому protobuf-net никогда не предлагается десериализовать .

Два варианта:

Вариант 1

использовать конфигурацию, а не код , чтобы определить использование protobuf; Преимущество этого заключается в том, что его можно использовать без каких-либо изменений на клиентском или сервере.

Вариант 2

не используйте сгенерированную оболочку службы - общий аналог может быть записан просто как:

public class Client<T> : ClientBase<T> where T : class
{
    public T Service { get { return Channel; } }
        public Client() {
    }

    public Client(string endpointConfigurationName) : 
            base(endpointConfigurationName) {
    }

    public Client(string endpointConfigurationName, string remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public Client(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(binding, remoteAddress) {
    }
}

Тогда потребляйте как:

using (var svc = new Client<IService1>())
{
    var data = svc.Service.GetActivities();
}
1 голос
/ 28 октября 2010

Я не знаю, от макушки головы; Я могу расследовать, но не прямо сейчас. В качестве прагматического обходного пути (пока я не смогу найти причину), возможно, вернуть что-то вроде ActivityResult класса, который содержит a List<ActivityCategoryDTO> в качестве члена?

...