带有实现接口的抽象基 class 的 WCF 不能正确序列化?

WCF with abstract base class with implemented interfaces does not serialize properly?

在服务方面,我有一个抽象基础 class,如下所示:

[DataContract]
public abstract class EntityBase : IObjectState, IDatabaseMetaData
{
    [NotMapped]
    [DataMember]
    public ObjectState ObjectState { get; set; }

    #region IDatabaseMetaData Members

    [DataMember] public DateTime InsertDatetime { get; set; }
    [DataMember] public int InsertSystemUserId { get; set; }
    [DataMember] public DateTime? UpdateDatetime { get; set; }
    [DataMember] public int? UpdateSystemUserId { get; set; }

    public virtual SystemUser InsertSystemUser { get; set; }
    public virtual SystemUser UpdateSystemUser { get; set; }

    #endregion
}

这是一个实现class(数据契约):

[DataContract(Namespace = Constants.MyNamespace)]
public class AccountClass : EntityBase
{
    [DataMember] public int AccountClassId { get; set; }
    [DataMember] public string AccountClassCode { get; set; }
    [DataMember] public string AccountClassDesc { get; set; }
}

在客户端,我基本上有重复的合同。这是 Client.AccountClass:

public class AccountClass : ObjectBase
{
    private int _accountClassId;
    private string _accountClassCode;
    private string _accountClassDesc;

    public int AccountClassId
    {
        get { return _accountClassId;}
        set
        {
            if (_accountClassId == value) return;

            _accountClassId = value;
            OnPropertyChanged(() => AccountClassId);
        }
    }
    public string AccountClassCode
    {
        get { return _accountClassCode; }
        set
        {
            if (_accountClassCode == value) return;

            _accountClassCode = value;
            OnPropertyChanged(() => AccountClassCode);
        }
    }
    public string AccountClassDesc
    {
        get { return _accountClassDesc; }
        set
        {
            if (_accountClassDesc == value) return;

            _accountClassDesc = value;
            OnPropertyChanged(() => AccountClassDesc);
        }
    }
}

..这里是 ObjectBase 的重要部分:

public abstract class ObjectBase : IObjectState, IDatabaseMetaData
{
    public ObjectState ObjectState { get; set; }

    #region IDatabaseMetaData Members

    public DateTime InsertDatetime { get; set; }
    public int InsertSystemUserId { get; set; }
    public DateTime? UpdateDatetime { get; set; }
    public int? UpdateSystemUserId { get; set; }

    #endregion
}

当我在 WcfMessageInspector.BeforeSendReply 中调试服务时,我可以看到正确发送 IObjectState 和 IDatabaseMetaData 值的消息。但是,在客户端,它们始终为空(或默认值)。我尝试使用 KnownTypes,将名称空间应用于抽象 class。我可以正确序列化所有内容的唯一方法是将接口和基础 classes 全部删除,并将属性直接放在 Client/Server AccountClass 对象上。我在这里错过了什么?谢谢。

更新 1 这似乎是一个名称空间的事情。如果我将我的 EntityBase 和 ObjectBase 移动到同一个 CLR 命名空间,一切正常(没有 KnownType 属性)。在我的客户合同的 AssemblyInfo.cs 文件中,我有这个:

[assembly: ContractNamespace(Constants.MyNamespace, ClrNamespace = "Project.Name.Client.Entities")]

我尝试在此处添加 ContractNamespaces 无济于事。就像我说的,除非 EntityBase 和 ObjectBase 在同一个命名空间中,否则它不会工作。然而,这对我来说是个问题,因为它创建了一个循环引用,除非我移动了很多东西。

知道如何查看完整的数据协定(名称空间、DataMembers 等)只是 client/server 上的 before/after 序列化吗?我尝试拦截 OnSerializing 事件,但运气不佳。再次感谢。

这是一个命名空间问题。 我明确地向所有相关方添加了正确的名称空间,并且一切正常。我注意到的一件事是 AssemblyInfo.cs 文件中的 ContractNamespace 的 ClrNamespace 应该与 AssemblyTitle 相匹配。此外,在 AssemblyInfo.cs 中放置多个 ContractNamespace 也没有任何作用。例如,我这样做:

[assembly: ContractNamespace(Constants.MyNamespace, ClrNamespace = "Company.Project.Client.Entities")]
[assembly: ContractNamespace(Constants.MyNamespace, ClrNamespace = "Company.Project.Client.Entities.Core")]

Company.Project.Client.Entities.Core 中的任何 POCO 都不会正确序列化,除非我像这样明确地将 DataContract 命名空间放在上面

[DataContract(Namespace = Constants.MyNamespace)]
public class SomeObject 
{
    [DataMember] public string SomeProperty { get; set; }
    //..etc
}

或者,我可以重组项目,使 SomeObject 位于 Company.Project.Client.Entities 命名空间中,这样就可以了。

最后,对调试最有帮助的是查看 WSDL,然后使用自定义 IDispatchMessageInspector 查看实际消息 AfterReceiveRequest 和 BeforeSendReply。希望这对某人有所帮助。