具有已实现接口的抽象基类的WCF无法正确序列化?

时间:2015-05-27 16:21:22

标签: wcf

在服务方面,我有一个像这样的抽象基类:

[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
}

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

[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值。但是,在客户端,它们始终为null(或默认值)。我尝试过使用KnownTypes,将名称空间应用于抽象类。我能正确序列化所有内容的唯一方法是将所有接口和基类放在一起,并将属性直接放在Client / Server AccountClass对象上。我在这里错过了什么?感谢。

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

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

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

我知道在客户端/服务器上序列化之前/之后我怎么能看到完整的数据契约(名称空间,DataMembers等)是什么样的?我试图在没有太多运气的情况下拦截OnSerializing事件。再次感谢。

1 个答案:

答案 0 :(得分:1)

这是命名空间问题。 我明确地向所有参与方添加了正确的命名空间,一切都很好。我注意到的一件事是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。希望这有助于某人。