WCF - 在 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 类中的构造函数,并且仍然具有 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您使用默认的 DataContractSerializer 来序列化您的对象,那么,是的,您的构造函数不会被序列化,并且当对象被反序列化时,您的客户端将不会调用其中可能包含的任何逻辑。
关于删除构造函数逻辑并填充嵌套
Address
类的问题,这将由DataContractSerializer
处理。如果我有这样的代码:然后从服务方法返回该代码,则该
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 theDataContractSerializer
. If I have code like this:and then return that from a service method, that
Customer
object will be serialized properly along with theAddress
information. The proxy on the client that's generated will know aboutAddress
and will be able to deserialize the stream coming from the service method to properly construct yourCustomer
object. YourCustomer
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.
如果您生成客户端(使用 svcutil 或“添加服务引用”),则生成的 DataContract 将如下所示:
您的实现详细信息不会保留。生成的所有内容都会进入 WSDL,在本例中只是
[DataMember]
属性。我提到这一点是因为您最初的问题是:“如果我生成代理会发生什么”。
如果这是从服务器发送到客户端的对象,那么您始终可以在将其发送到客户端之前初始化 CustomerAddress。事实上,如果您的原始代码位于服务器上,那么该构造函数将运行,并且 WCF 将序列化
CustomerAddress
并且基本上永远不会发送 null (除非您在构造函数之后将其设置回 null)。如果您想让客户端始终向您发送
CustomerAddress
,那么您可以:if(x.CustomerAddress == null) x.CustomerAddress = new Address();
[DataMember(IsRequired=true)] public地址CustomerAddress;
否则,我认为没有任何方法可以强制生成的 WCF 客户端为您初始化该字段。
If you generate the client (using svcutil or "add service reference"), then the generated DataContract will look like:
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:if(x.CustomerAddress == null) x.CustomerAddress = new Address();
[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.
您最好在程序集中定义所有数据协定类,并让服务器项目和客户端项目都引用该程序集,以便可以共享初始化行为。生成服务引用时,您可以指示代码生成器使用现有的数据协定类。
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.