WCF - 在DataContract构造函数中实例化对象

时间:2011-09-16 22:22:21

标签: wcf constructor datacontract

我有两个课程如下:

[DataContract]
public class Address
{
   [DataMember]
   public string Line1
   [DataMember]   
   public string Line2
   [DataMember]
   public string City
   [DataMember]
   public string State
   [DataMember]
   public string Zip
}

[DataContract]
public class Customer
{
   public Customer()
   {
      CustomerAddress = new Address();
   }

   [DataMember]
   public string FirstName
   [DataMember]
   public string LastName
   [DataMember]
   public Address CustomerAddress
}

如果我生成使用Customer类的服务代理,会发生什么?如果我正确理解了这个概念,那么我认为Customer类中的构造函数不会在客户端被调用,它可能会给出不同的行为。

如何摆脱Customer类中的构造函数,并且仍然具有CustomerAddress类型的Address属性,以使其表现为一个愚蠢的DTO对象?

人们用来避免这种情况的一般准则或最佳做法是什么?

3 个答案:

答案 0 :(得分:6)

如果您使用默认的DataContractSerializer来序列化您的对象,那么,是的,您的构造函数未被序列化,并且当反序列化对象时,您的客户端将不会调用您可能拥有的任何逻辑。 / p>

关于删除构造函数逻辑并填充嵌套Address类的问题,DataContractSerializer将对此进行处理。如果我有这样的代码:

Customer c = new Customer() { 
  FirstName = "David",
  LastName = "Hoerster",
  CustomerAddress = new Address() {
    Line1 = "1 Main Street",
    City = "Smallville",
    State = "AA",
    Zip = "12345"
  }
};

然后从服务方法返回,Customer对象将与Address信息一起正确序列化。生成的客户端上的代理将知道Address,并且能够反序列化来自服务方法的流以正确构建您的Customer对象。你的Customer将是一个虚拟DTO - 没有逻辑,只有属性。

在WCF序列化中查看Aaron Skonnard的MSDN article,在那里他谈到了DataContractSerializer。

答案 1 :(得分:1)

如果你生成客户端(使用svcutil或“添加服务引用”),那么生成的DataContract将如下所示:

[DataContract]
public class Customer
{
   // empty default constructor
   public Customer()
   {
   }

   [DataMember]
   public string FirstName
   [DataMember]
   public string LastName
   [DataMember]
   public Address CustomerAddress
}

您的实施细节不会结转。所有生成的都是WSDL中的内容,在这种情况下只是[DataMember]属性。

我之所以提到这一点是因为您的原始问题是:“如果我生成代理将会发生什么。”


如果这是从服务器发送到客户端的对象,那么您可以在将CustomerAddress发送到客户端之前始终初始化它。事实上,如果您的原始代码在服务器上,那么将运行该构造函数,并且WCF将序列化CustomerAddress并且基本上从不发送null(除非您在构造函数之后将其设置回null)。

如果您想让客户端始终向您发送CustomerAddress,那么您可以:

  • 服务器检查为null,例如if(x.CustomerAddress == null) x.CustomerAddress = new Address();
  • 根据需要标记DataMember,如果客户端没有传递任何内容,服务器将返回错误:[DataMember(IsRequired=true)] public Address CustomerAddress;

否则,我认为没有办法强制生成的WCF客户端为您初始化该字段。

答案 2 :(得分:0)

您最好定义程序集中的所有数据协定类,并将服务器项目和客户端项目引用到程序集,以便可以共享初始化行为。生成服务引用时,可以指示代码生成器使用现有的数据协定类。