我有一个WCF服务公开两个操作 - IncrementList()和GetList()。客户端B连接到服务,调用GetList()并显示给用户。客户端A可以通过调用IncrementList()来更新此列表 我希望客户端B在调用IncrementList()时得到通知,这样它可以再次调用GetList()来显示更新的数据。
您能否概述一下如何实现这一点?回调?复式?发布/订阅?
WCF 4.0中有哪些新功能可以帮助实现这种情况?
谢谢!
答案 0 :(得分:5)
您应该事先决定的是,如果您想将整个列表增加(重)或仅更新项目推送到每个客户端。下面的代码用于推送整个列表,但很容易修改它只是为了推送更新的对象(推荐)
在应用启动时,客户B应致电Register_client
,然后致电GetList
。随后,当列表递增时,将通过回调通知它(客户端需要支持此接口)
来电GetList
需要双工频道和SessionMode.Required
。
您的服务器应该恭维:
[ServiceContract(SessionMode = SessionMode.Required
CallbackContract = typeof(IMyCallback))]
public interface IMyServer {
[OperationContract]
void Register_client();
[OperationContract(IsOneWay = true)]
void IncrementList();
[OperationContract]
ListObject[] GetList();
}
[DataContract]
public class ListObject {
[DataMember]...
}
您的客户应该恭维:
public interface IMyCallback {
[OperationContract(IsOneWay = true)]
void PushList(ListObject[] list);
}
注册客户端只需要存储客户端回调接口,以便在列表增加时使用:
public override void Register_client() {
// Store callback interfaces for all connected clients:
IMyCallback callback = OperationContext.Current.GetCallbackChannel<IGatewayServerCallback>();
if (clients.Contains(callback) == false)
clients.Add(callback);
Trace.WriteLine(string.Format("Client connection established ({0})", clients.Count));
}
其中:
private List<IMyCallback> clients = new List<IMyCallback>();
IncrementList
的impliementation应该进行回调以将新列表(或者更好的只是添加到列表中的新对象)推送到客户端 - 例如:
for (int i = 0; i < clients.Count; i++) {
if (((ICommunicationObject)clients[i]).State == CommunicationState.Opened) {
try {
clients[i].PushList(list);
}
catch (Exception e) {
clients.RemoveAt(i--);
Trace.WriteLine(e);
Trace.WriteLine(string.Format("Removing client {0} (exception).", i + 1));
}
}
回调实现(客户端)看起来像:
public class MyCallback : IMyCallback {
public void PushList(ListObject[] list) {
// Were client side - update list code here...
}
这个回调实现可能需要引用一些保存列表数据的对象 - 可能会将其传递给构造函数(未显示)。
当您实例化代理对象时,您需要将回调实例传递给代理构造函数 - 类似于:
MyServerClient client_proxy = new MyServerClient(new InstanceContext(my_callback, binding_str)