积极答复者
WCF怎样暴露自己的实体接口?

问题
-
答案
-
Hi,
你的这个情况我没试验过。不过问题应该和序列化有关系。一般情况下用户自己定义的实体类。要想在客户端与服务端共享的话,
只能是定义为数据契约。这样的话数据在客户端和服务端传递的时候,WCF会调用自己特定的序列化器DataContractSerializer来序列换这个对象。
你把实体类添加Datacontract属性,如果特定的字段如果想暴露给客户端的话,在加上Datamemeber标记。
以前英文论坛也有人讨论过这个问题,就是数据契约和实体类的服用问题。为了能使实体类支持数据契约序列化与饭序列化
可能需要花费一定的时间来标记实体类的数据契约属性。
另外一种如果客户端也是基于.NET2.0以上 平台的话,也可以使用XML序列化标记,就是在类的生命前,加上Serializable关键字。
Frank Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum- 已标记为答案 韦恩卑鄙 waywa 2009年8月3日 9:22
-
http://book.51cto.com/art/200908/141215.htm
5.3.3 基于接口的序列化DataContractSerializer的创建必须基于某个确定的类型,这里的类型既可以是接口,也可以是抽象类或具体类。不过基于接口的DataContractSerializer与基于抽象数据契约类型的DataContractSerializer,在进行序列化时表现出来的行为是不相同的。
在下面的代码中,在调用Serialize<T>的时候,将泛型类型分别设定为接口IOrder和抽象类OrderBase。虽然是对同一个Order对象进行序列化,但是序列化生成的XML却各有不同。文件order.interface.xml的根节点为<z:anyType>,这是因为DataContractAttribute不能应用于接口上面,所以接口不具有数据契约的概念。<z:anyType>表明能够匹配任意类型,相当于类型object。
- Order order = new Order()
- {
- ID = Guid.NewGuid(),
- Customer = "NCS",
- Date = DateTime.Today,
- ShipAddress = "#328, Airport Rd, Industrial
Park, Suzhou Jiangsu Province", - TotalPrice = 8888.88
- };
- Serialize<IOrder>(order, @"E:\order.interface.
xml", new List<Type>{typeof - (Order)});
- Serialize<OrderBase>(order, @"E:\order.class.
xml", new List<Type> - { typeof(Order) });
- <z:anyType xmlns:i="http://www.w3.org/2001/
XMLSchema-instance" - xmlns:d1p1="http://schemas.datacontract.org/2004/07/Artech.
- DataContractSerializerDemos" i:type="d1p1:Order"
- xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
- <d1p1:Customer>NCS</d1p1:Customer>
- <d1p1:Date>2008-12-04T00:00:00+08:00</d1p1:Date>
- <d1p1:ID>04c07e41-6302-48d1-ac06-87ebbff2b75f</d1p1:ID>
- <d1p1:ShipAddress>#328, Airport Rd,
Industrial Park, Suzhou Jiangsu - Province</d1p1:ShipAddress>
- <d1p1:TotalPrice>8888.88</d1p1:TotalPrice>
- </z:anyType>
- <OrderBase xmlns:i="http://www.w3.org/2001/
XMLSchema-instance" i:type="Order" - xmlns="http://schemas.datacontract.org/2004/07/Artech.
- DataContractSerializerDemos">
- <Customer>NCS</Customer>
- <Date>2008-12-04T00:00:00+08:00</Date>
- <ID>04c07e41-6302-48d1-ac06-87ebbff2b75f</ID>
- <ShipAddress>#328, Airport Rd, Industrial Park, Suzhou Jiangsu
- Province</ShipAddress>
- <TotalPrice>8888.88</TotalPrice>
- </OrderBase>
实际上,在WCF应用中,如果服务契约的操作参数定义为接口,在发布出来的元数据中,接口类型就相当于object,并且当客户端通过添加服务引用生成客户端服务契约的时候,相应的参数类型就是object类型。比如对于下面的服务契约的定义,当客户端导出后将变成后面的样式。
看来只能用Object 了 不过看起来应该没什么问题哦- [ServiceContract(Namespace="http://www.artech.com/")]
- public interface IOrderManager
- {
- [OperationContract]
- void ProcessOrder(IOrder order);
- }
- [System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", - "3.0.0.0")]
- [System.ServiceModel.ServiceContract
Attribute(ConfigurationName = - "ServiceReferences.IOrderManager")]
- public interface IOrderManager
- {
- [System.ServiceModel.OperationContract
Attribute(Action = - "http://www.artech.com/IOrderManager/
ProcessOrder", ReplyAction = - "http://www.artech.com/IOrderManager/
ProcessOrderResponse")] - void ProcessOrder(object order);
- }
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。- 已标记为答案 韦恩卑鄙 waywa 2009年8月3日 9:22
全部回复
-
Hi,
你的这个情况我没试验过。不过问题应该和序列化有关系。一般情况下用户自己定义的实体类。要想在客户端与服务端共享的话,
只能是定义为数据契约。这样的话数据在客户端和服务端传递的时候,WCF会调用自己特定的序列化器DataContractSerializer来序列换这个对象。
你把实体类添加Datacontract属性,如果特定的字段如果想暴露给客户端的话,在加上Datamemeber标记。
以前英文论坛也有人讨论过这个问题,就是数据契约和实体类的服用问题。为了能使实体类支持数据契约序列化与饭序列化
可能需要花费一定的时间来标记实体类的数据契约属性。
另外一种如果客户端也是基于.NET2.0以上 平台的话,也可以使用XML序列化标记,就是在类的生命前,加上Serializable关键字。
Frank Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum- 已标记为答案 韦恩卑鄙 waywa 2009年8月3日 9:22
-
http://book.51cto.com/art/200908/141215.htm
5.3.3 基于接口的序列化DataContractSerializer的创建必须基于某个确定的类型,这里的类型既可以是接口,也可以是抽象类或具体类。不过基于接口的DataContractSerializer与基于抽象数据契约类型的DataContractSerializer,在进行序列化时表现出来的行为是不相同的。
在下面的代码中,在调用Serialize<T>的时候,将泛型类型分别设定为接口IOrder和抽象类OrderBase。虽然是对同一个Order对象进行序列化,但是序列化生成的XML却各有不同。文件order.interface.xml的根节点为<z:anyType>,这是因为DataContractAttribute不能应用于接口上面,所以接口不具有数据契约的概念。<z:anyType>表明能够匹配任意类型,相当于类型object。
- Order order = new Order()
- {
- ID = Guid.NewGuid(),
- Customer = "NCS",
- Date = DateTime.Today,
- ShipAddress = "#328, Airport Rd, Industrial
Park, Suzhou Jiangsu Province", - TotalPrice = 8888.88
- };
- Serialize<IOrder>(order, @"E:\order.interface.
xml", new List<Type>{typeof - (Order)});
- Serialize<OrderBase>(order, @"E:\order.class.
xml", new List<Type> - { typeof(Order) });
- <z:anyType xmlns:i="http://www.w3.org/2001/
XMLSchema-instance" - xmlns:d1p1="http://schemas.datacontract.org/2004/07/Artech.
- DataContractSerializerDemos" i:type="d1p1:Order"
- xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
- <d1p1:Customer>NCS</d1p1:Customer>
- <d1p1:Date>2008-12-04T00:00:00+08:00</d1p1:Date>
- <d1p1:ID>04c07e41-6302-48d1-ac06-87ebbff2b75f</d1p1:ID>
- <d1p1:ShipAddress>#328, Airport Rd,
Industrial Park, Suzhou Jiangsu - Province</d1p1:ShipAddress>
- <d1p1:TotalPrice>8888.88</d1p1:TotalPrice>
- </z:anyType>
- <OrderBase xmlns:i="http://www.w3.org/2001/
XMLSchema-instance" i:type="Order" - xmlns="http://schemas.datacontract.org/2004/07/Artech.
- DataContractSerializerDemos">
- <Customer>NCS</Customer>
- <Date>2008-12-04T00:00:00+08:00</Date>
- <ID>04c07e41-6302-48d1-ac06-87ebbff2b75f</ID>
- <ShipAddress>#328, Airport Rd, Industrial Park, Suzhou Jiangsu
- Province</ShipAddress>
- <TotalPrice>8888.88</TotalPrice>
- </OrderBase>
实际上,在WCF应用中,如果服务契约的操作参数定义为接口,在发布出来的元数据中,接口类型就相当于object,并且当客户端通过添加服务引用生成客户端服务契约的时候,相应的参数类型就是object类型。比如对于下面的服务契约的定义,当客户端导出后将变成后面的样式。
看来只能用Object 了 不过看起来应该没什么问题哦- [ServiceContract(Namespace="http://www.artech.com/")]
- public interface IOrderManager
- {
- [OperationContract]
- void ProcessOrder(IOrder order);
- }
- [System.CodeDom.Compiler.GeneratedCodeAttribute
("System.ServiceModel", - "3.0.0.0")]
- [System.ServiceModel.ServiceContract
Attribute(ConfigurationName = - "ServiceReferences.IOrderManager")]
- public interface IOrderManager
- {
- [System.ServiceModel.OperationContract
Attribute(Action = - "http://www.artech.com/IOrderManager/
ProcessOrder", ReplyAction = - "http://www.artech.com/IOrderManager/
ProcessOrderResponse")] - void ProcessOrder(object order);
- }
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。- 已标记为答案 韦恩卑鄙 waywa 2009年8月3日 9:22
-
谢谢,我也是学习了新东西~
Frank Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum -
您好,可以考虑用基类来替换接口:
public abstract class ItemBase :IItem
{
abstract value {get;set;}
}
IService1 中加入
void Add(ItemBase itm);
虽然也支持多态,但这样会改变该服务契约的语义,传入的参数不再是某个功能集而是一个责任体。这要看具体的需求而定了。
好处是增强了类型的安全。
这样是不是还存在客户端无法序列化的问题,估计还是要声明为数据契约
Frank Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum -
是,我忘了给ItemBase加[DataContract]特性了。
这样就违背使用接口的最初需求了, 不行啊。目前看可能还是要在客户端实现 IRepository<IItem> 数据契约仍然要用实体类 而不是接口。
如果契约依赖实体类的话 EF/Linq2sql/NH 就要实现三套接口了 不甘心啊。
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。
您好,我之前也遇到这类的问题,因接口的继承跟类和抽象类的继承不同。
现在对参数和泛型参数都特别小心,在一开始设计时就先确认,这参数是代表接口的功能集,还是代表抽象类的责任体。
另,从《Programming WCF Services》摘一段跟您发布主题相关的。估计可以做结论了。请参考:
"You cannot apply the KnownType attribute on the base interface because the interface itself will not be included in the exported metadata. Instead, the exported service contract will be object-based"