2011-06-11 80 views
8

当我在客户端上创建DataContract的实例时,我需要某些数据成员获取一些值。这不是使用构造函数发生的。我搜索了不同的论坛,发现我们必须使用[OnDeserializing]和[OnDeserialized]属性。这也不起作用。有人可以在这里提出一些建议。另一种选择是在客户端的部分类中创建构造函数。我想避免这种情况。WCF DataContract中的构造函数未反映在客户端上

请找到下面的代码:

服务器端:Datacontract

[DataContract] 
public class Account 
{ 

    private int mAccountId; 
    private string mAccountName; 

    public Account() 
    { 
     mAccountId = 5; 
     mAccountName = "ABC"; 
    } 

    [OnDeserializing] 
    public void OnDeserializing(StreamingContext context) 
    { 
     mAccountId = 5; 
     mAccountName = "ABC"; 
    } 

    [OnDeserialized] 
    public void OnDeserialized(StreamingContext context) 
    { 

    } 

    [DataMember] 
    public int AccountId 
    { 
     get 
     { 
      return mAccountId; 
     } 
     set 
     { 
      mAccountId = value; 
     } 
    } 

    [DataMember] 
    public string AccountName 
    { 
     get 
     { 
      return mAccountName; 
     } 
     set 
     { 
      mAccountName = value; 
     } 
    } 


} 

客户端 - 初始化

namespace TestClient 
{ 
    public partial class _Default : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      Account acc = new Account(); 

     } 
    } 
} 
+0

WCF客户端 - 服务器的连接** **只镜像数据的合同数据方面 - ** **没有任何代码,你可能在你的数据类。毕竟:仅数据可以序列化成由XSD(XML模式)所示的格式,并通过线路发送 - 没有代码。 – 2011-06-11 19:15:22

回答

14

用于创建WCF代理类的代码生成器创建兼容的合同类型,并没有使用与W​​CF服务使用的完全相同的类型。达到你想要的最简单的方法,就是你的客户端上创建自己的构造函数,因为生成的代码是partial

partial class Account 
{ 
    public Account() 
    { 
     AcountId = 5; 
     AccountName = "ABC"; 
    } 
} 

如果你不想这样做,你可以得到WCF重用类型已被您的客户项目引用。因此,如果数据约定类位于单独的库中(如建议的那样),则可以引用该库,然后重新配置WCF客户端项目以重用引用程序集中的共享类型。

+0

任何其他解决方法?为什么[OnDeserializing]/[OnDeserialized]属性不工作.....谢谢... – Subhasis 2011-06-11 13:32:17

+0

因为这些属性是反序列化=当您从服务而不是当你调用构造函数得到'Account'! – 2011-06-11 13:42:18

+2

+1将数据合同类放入另一个库中。我们已经把它们放在与服务接口定义库,并在现实中交流的合同是服务的关注,而不是域模型的关注。 – 2011-06-11 14:01:29

13

归因于DataMember属性的属性仅定义了将包含在生成的WSDL/XSD中的内容。客户端将根据wsdl/xsd生成自己的类用于与服务进行通信。它不使用在服​​务器上使用的相同的类。

这就是为什么你不会得到:

  • DataContract类定义的任何构造
  • 任何私人[DataMember]性能/场(客户端总是会产生公共属性/字段)
  • 任何行为定义在DataContract类中

想象一下,java客户端想要连接到您的服务的场景。你期望用相同的构造函数生成java类吗?那么[OnDeserialized]属性呢?怎么样一个Java脚本客户端,或Python客户端?

当你开始以这种方式思考它的时候,你开始明白为什么你不能拥有你想要的东西(至少不是没有在客户端和服务器之间共享库)。

实际情况是,您不能强制客户端拥有始终具有默认值的类,并且客户端无法始终发送有效数据,但客户端始终可以发送包含垃圾的消息(如果需要)。您可以使用IsRequired和'EmitDefaultValue`来控制消息的某些方面,它会将检查添加到xsd中以确保消息中存在某些内容,但您必须在服务器上进行验证,但不能假定你得到的对象将被验证。

我的建议是从你的域对象创建DTO的跨线,其中不包含任何形式的检查派,他们只是简单的袋保存数据。然后创建工厂以将您的域对象转换为DTO和DTO到客户端对象中。工厂只需要DTO并将成员传递给域对象的构造函数。那么你的验证逻辑可以存在于它所属的域对象的构造函数中。有了方法,你现在有你最终可能会稍微扭所以它可以从两个构造,并在[OnDeserialized]的方法来进行验证。