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

发布于 2024-12-04 18:37:43 字数 770 浏览 0 评论 0原文

我有如下两个类:

[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 类中的构造函数,并且仍然具有 Address 类型的 CustomerAddress 属性,以便它表现得像一个愚蠢的 DTO 对象?

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

I have two classes as below:

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

What will happen if i generate proxy of my service that uses Customer class? If i understand the concept correctly then i think the constructor in the Customer class will not be called at the client side and it may give different behavior.

How do i get rid of that constructor in the Customer class and still have the CustomerAddress property of type Address so that it behaves as a dumb DTO object?

What is the general guideline or best practices that people use to avoid this situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

北斗星光 2024-12-11 18:37:43

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

关于删除构造函数逻辑并填充嵌套 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——没有逻辑,只有属性。

查看 Aaron Skonnard 关于 WCF 序列化的 MSDN 文章,其中讨论了 DataContractSerializer 。

If you use the default DataContractSerializer to serialize your objects, then, yes, your constructor is not serialized, and any logic you may have in it will not be called by your client when the object is deserialized.

Regarding your question about removing the constructor logic and having the nested Address class be populated, that will be taken care of by the DataContractSerializer. If I have code like this:

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

and then return that from a service method, that Customer object will be serialized properly along with the Address information. The proxy on the client that's generated will know about Address and will be able to deserialize the stream coming from the service method to properly construct your Customer object. Your Customer will be a dummy DTO -- no logic, just properties.

Check out Aaron Skonnard's MSDN article on WCF Serialization where he talks about the DataContractSerializer.

歌入人心 2024-12-11 18:37:43

如果您生成客户端(使用 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地址CustomerAddress;

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

If you generate the client (using svcutil or "add service reference"), then the generated DataContract will look like:

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

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

Your implementation details are not carried over. All that is generated is what goes into the WSDL, which is just the [DataMember] properties in this case.

I mention this because your original question asks: "What will happen if i generate proxy".


If this is an object being sent from the server to the client, then you can just always initialize CustomerAddress before sending it to the client. Infact, if your original code is on the server, then that constructor will be run, and WCF will serialize the CustomerAddress and basically never send a null (unless you set it back to null after the constructor).

If you want to make it so that the client always sends you a CustomerAddress, then you could:

  • have the server check for null, like if(x.CustomerAddress == null) x.CustomerAddress = new Address();
  • mark the DataMember as required, then the server will return an error if the client did not pass anything: [DataMember(IsRequired=true)] public Address CustomerAddress;

Otherwise, I don't think there is any way to force the generated WCF client to initialize that field for you.

开始看清了 2024-12-11 18:37:43

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

You'd better define all the data contract classes in a assembly and have both server project and client project reference to the assembly so the initialization behaviour can be shared. When generating service reference, you can instruct the code generator to use existing data contract classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文