I have a service decorated with a ServiceContract attribute, and the interface definition is something like this:
[ServiceContract(CallbackContract = typeof(ITabularPushCallback))] public interface ITabularPushService { [OperationContract(IsOneWay = true)] void Subscribe(int tableId); [OperationContract(IsOneWay = true)] void UnSubscribe(int tableId); [OperationContract(IsOneWay = false)] bool IsSubscribed(int tableId); }
the callback contract of the interface ITabularPushService is ITabularCallback, the definition of the interface is like this:
public interface ITabularPushCallback { // this will ensure that the Datagram transport will be used, the Callback does not rquire that the server to block // and this is far more effecient than Bidirectional connection [OperationContract(IsOneWay = true)] void NotifyMessage(object[][] messages, int tableId); }
Notice it is not necessary to decorate the callback contract with the [ServiceContract] attribute, because
This is just an side note, let's get back to our question before.
Now suppose that we have a new requirement to add a new method to the ITabularCallback, something like the Server heartbeat, we don't want to directly extend the interface because we feel this is so general that we want to make a separate interface for the heartbeat. so we go ahead to implement the code as such.
/// <summary> /// Server HeartBeat interface /// </summary> public interface IHeartbeat { /// <summary> /// Server heartbeat /// </summary> /// <param name="timestamp">heartbeat timestamp</param> [OperationContract(IsOneWay = true)] void Heartbeat(long timestamp); }
then we will make our ITabularCallback interface to inherit from the IHeartbeat, quick and easy, shouldn't it be ? however, you might be greeted with a NotSupportedException. The messgae may contains the following.
Callback method Heartbeat is not supported, this can happen if the method is not marked with OperationContractAttribute or if its interface type is not the target of the ServiceContractAttribute's CallbackContract.
Huh?
So we figured out somehow that WCF does not walk the tree of interface and do reflection to get all Operatoin members. (For details, please see the References on topic Inheritance not supported on callback contracts?)
since as we have pointed out, the ServiceContract willl forward interface to WCF system, so we can leverage this point. we can make a marker interface and decorate that with a ServiceContract attribute, which shall binds to Callback we have in mind - IHeartbeat, we caller the new interface IHeartbeatService, it is an empty interface, which serves here only for its side effect of ServiceContract attribute to forward its callback contract.
// Check // http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/ef896836-dec1-4fa6-9956-e3a4958643ce [ServiceContract(CallbackContract = typeof(IHeartbeat))] public interface IHeartbeatService { }
Now we have to refine the Service and its contract together...
[ServiceContract(CallbackContract = typeof(ITabularPushCallback))] public interface ITabularPushService : IHeartbeatService { // same as before }
and the new ITabularCallback interface.
public interface ITabularPushCallback : IHeartbeat { // ... same as before. }
now that both the IHeartbeat and ITabularCallback is forwarded you will not worry about getting the NotSupported excetion.
Explain on the Design:
Suppose that we have
[ServiceContract(Namespace="foo", CallbackContract=typeof(IBaseCB))] interface IBaseC { ... } interface IBaseCB : IBaseBaseCB { ... } interface IBaseBaseCB { [OperationContract] void F(); }
If we have reflection which goes up the tree, then it will have a F method in the namespace foo.
Now, if we add more interface, such as
[ServiceContract(Namespace="bar", CallbackContract=typeof(IBaseBaseCB))] interface IOther { ... }
then we might have another F in namespace "bar".
Now, we refine as such
interface IDerivedCB : IBaseCB { ...} [ServiceContract(CallbackContract=typeof(IDerivedCB))] interface IDerivedC : IBaseC, IOther { ... }
Then how can wcf know which namespace F now in IDerviedC is?
Some other tips:
1. putting [ServiceContract] attribute on a callback contract
To model two servers
[ServiceContract(CallbackContract=typeof(IPong)] interface IPing { ... } [ServiceContract(CallbackContract=typeof(IPing)] interface IPong { ... }
Or even make that to a single contract (Peerchannel does this a bit)
[ServiceContract(CallbackContract=typeof(ISelf)] interface ISelf { ... }
References:Inheritance not supported on callback contracts?
相关推荐
wpf-wcf-wf整合开发实例--有利于理解wpf-wcf-wf的整合
WCF--DEMO 在GLD写的第一个DEMO 用到简单的WCF客户端代理类
WCF--system.serviceModel配置属性说明[借鉴].pdf
WCF-学习资料汇总 详细描述WCF的各种处理,配置, 开发中的对操作和数据的抽象 。
实践WCF中的MessageContract与IXmlSerializable
一个WCF的入门——helloWCF 专给第一次写WCF程序的人
WCF学习的相关资料,这些都是我从网上收集整理的,想学习的人有福啦
WCF 项目应用连载[4] - 自定义配置 扩展ServiceHost - LServiceHost WCF 项目应用连载[5] - 自定义配置 扩展ChannelFactory<T> - LDuplex ———————————————————————————————— WCF...
开发工具VS2013 一个简单的Demo解决方案实现以下需求: 多台Host根据XML配置指定某一地址为主服务地址 客户端优先连接主服务Host,当主服务机断连自动检测并连接分服务机,当主服务机恢复服务,自动连回主服务机
国外高校的WCF PPT讲义,很生动的。
Spring.net整合WCF在Winfrom应用程序下调用WCF Spring.NET整合Winfrom
gRPC for WCF Developers
NHibernate+WCF项目实战
WCF结合winform写了,写了个登录跟人员信息获取。懒得写了,而且用了静态工厂结合EF和T4模板。知识点比较多的,入门的可以看看。
一个silverlight 图片上传,下载的功能, 配置WCF,可以上传4m图片,
Windows通信基础(Windows Communication Foundation,WCF)是基于Windows平台下开发和部署服务的软件开发包(Software Development Kit,SDK)。
简单易懂,快速了解WCF如何CallBack
js跨域请求windows服务,用vs打开后,运行Golden.Demo.ConsoleApp程序,再在浏览器访问“http://localhost:18086/TestService/1”
WCF学习资料_DOC文档,从基础到复杂的介绍WCF知识;wcf学习之端点绑定;wcf学习之服务契约;wcf学习之异步调用;wcf学习之异常处理;WCF - ChannelFactory;WCF - Callback等等
WCF-REST- 电子银行:在线银行系统是使用REST WCF服务开发的。 .NET Framework用作客户端。