类定义之外的 WCF 序列化信息
假设这个简单的场景: 我的客户有一个已经运行的 .net 应用程序,他/她希望通过 WCF 公开一些功能。所以他给了我一个程序集,其中包含一个公开以下方法的公共类。
OrderDetail GetOrderDetail (int orderId) // Suppose OrderDetail has {ProductId, Quantity, Amount)
现在,我希望 OrderDetail (Amount) 的某些成员不要被序列化。 根据 http://msdn.microsoft.com/en-us/library/aa738737 .aspx,执行此操作的方法是通过 [DataContract] 和 [DataMember]/[IgnoreDataMember] 属性。但是,这对我来说不是一个选择,因为我无法修改客户端的源代码。因此,我正在寻找一种方法来指定要在类型定义之外序列化哪些成员。看起来应该像这样:
[OperationContract]
[IgnoreMember(typeof(OrderDetail), "Amount" )]
OrderDetail QueryOrder(int orderId){
return OrderDetail.GetOrderDetail(orderId)
}
有什么办法做到这一点吗? 谢谢, 贝尔纳贝
Suppose this simple scenario:
My client has an already working .net application and he/she wants to expose some functionality through WCF. So he gives me an assembly, containg a public class that exposes the followig method.
OrderDetail GetOrderDetail (int orderId) // Suppose OrderDetail has {ProductId, Quantity, Amount)
Now, I want some members of OrderDetail (Amount) not to be serialized.
According to http://msdn.microsoft.com/en-us/library/aa738737.aspx, the way to do this is by means of the [DataContract] and [DataMember]/[IgnoreDataMember] attributes. However, that's not an option for me because I can not modify client's source code. So I'm looking for a way to specify which members I want to serialize out, outside the type's definition. Something that should look like this:
[OperationContract]
[IgnoreMember(typeof(OrderDetail), "Amount" )]
OrderDetail QueryOrder(int orderId){
return OrderDetail.GetOrderDetail(orderId)
}
Is there any way to to this?
Thanks,
Bernabé
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不要通过线路发送客户端对象,而是从仅包含您要发送的信息的客户端对象创建 DTO,然后发送该信息。
这使您可以准确控制发送的信息,并且符合传递消息而不是对象的 WCF 意图。
因此,创建一个
OrderDetailDto 类
并使用OrderDetail< 中的数据填充该类。 /code> 由调用客户端代码中的方法返回。使用
DataContract
和DataMember
属性装饰OrderDetailDto
(您可以在此处重命名该类,以便当 WCF 返回它时,它会以名称OrderDetail
)对客户端代码中的所有对象重复此操作,以便在服务边界处基本上从 DTO->Client 对象和 Client Objects->DTO
EDIT
虽然可能有一个选项允许您要求的内容(我不知道,但希望其他人可能会),但请考虑当您发送使用客户端对象作为 DTO 时,您将它们用于两个目的(客户端对象和消息契约),这违反了单一职责原则,当你在客户端获取它们时,它们将不是相同的客户端对象,只是具有相同属性的 DTO,你将无法在客户端获取行为侧面物体(至少并非没有在服务器端和客户端共享库)。
通过将数据契约绑定到对象,您最终还必须将客户端对象和数据契约的更改作为一件事来管理。当它们分开时,您可以管理对客户端对象的更改,而无需更改 DTO,您只需填充不同的内容即可。
虽然创建 DTO 看起来需要做很多工作,但最终我认为这是值得的。
Don't send the clients objects across the wire, create a DTO from the clients object containing only the information that you want to send and send that instead.
This allows you to control exactly what information gets sent, and is in keeping with the WCF intentions of passing messages and not objects
So create an
OrderDetailDto class
and populate this with the data from theOrderDetail
returned by the call to the method in the clients code. Decorate TheOrderDetailDto
with theDataContract
andDataMember
attributes (you can rename the class in here so that when it is returned by WCF it is returned with the nameOrderDetail
)Repeat this for all objects in the client code, so that at the service boundary you basically convert from DTO->Client objects and Client Objects->DTO
EDIT
Whilst there might be an option which allows what you have asked for (I am not aware of one, but hopefully someone else might be) consider that when you send use your client objects as DTOs you are using them for two purposes (the client object and the message contract), which is against the Single Responsibility Principle and when you get them on the client side they will not be the same client side objects, just DTOs with the same properties, you will not be able to get behaviour in the client side objects (at least not without sharing libraries on the server side and client side).
By binding the data contract to the objects you also end up having to manage the changes to client objects and data contracts as one thing. When they are separate you can manage the changes to client side objects without neccessarily changing the DTOs, you can just populate the differently.
Whilst it seems like it is a lot of work to create the DTOs, in the end I think it will be worth it.
您必须编写一个包装类,它仅公开所需的属性,并简单地调用客户端提供的类来获取其值。
唯一的其他选择是使用反射发出一个新的动态类并对其进行序列化(请参阅http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.aspx),但它可能不值得付出努力,除非您需要构建一个很多包装类。
You will have to write a wrapper class that only exposes the desired properties and simply calls the class your client provided to gets its values.
The only other option would be to emit a new dynamic class using reflection and serialize that (see http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.aspx), but its probably not worth the effort unless you need to build a lot of wrapper classes.