Protobuf.net WCF 反序列化 List<T>

4
我会尝试使用protobuf-net r.282来进行WCF。好的,我会为我的合同打上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时,在客户端得到了null。

通过fiddler我看到数据传输成功,所以我认为这是反序列化器的问题。

怎么了?我怎样才能在客户端获取列表?

编辑

似乎我遇到了所有列表的问题 :)

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

只有名称,字段列表为空,数据已全部传输,客户端收到了数据。


嗨,安德鲁 - 抱歉回复晚了;最近有很多事情“忙”着。以下进行分析和解释。 - Marc Gravell
2个回答

4

好的,我已经复现了问题。实际上这似乎是IDE/svcutil拒绝重用来自DTO程序集的服务契约(接口),即使它正在重用数据契约(类)。由mex生成的服务契约(接口)缺少必要的额外属性,因此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();
}

谢谢!它有效了。我遵循了扩展配置方式。但是现在我遇到了枚举问题。 - Andrew Kalashnikov

1
我不知道答案,但我可以调查一下,只是现在不行。作为一个实用的解决方法(在我找到原因之前),也许可以返回一个类似于 ActivityResult 的东西,其中包含一个 List<ActivityCategoryDTO> 作为成员?

不幸的是,这个解决方法并没有帮助我,我仍然没有找到解决方案。 - Andrew Kalashnikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接