带有实现接口的抽象基 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。希望这对某人有所帮助。
在服务方面,我有一个抽象基础 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。希望这对某人有所帮助。