WCF - 推荐客户端回调?

发布于 2024-12-13 13:36:10 字数 337 浏览 4 评论 0原文

我有一个 WCF 服务公开两个操作 - IncrementList() 和 GetList()。客户端 B 连接到服务,调用 GetList() 并向用户显示。客户端 A 能够通过调用 IncrementList() 来更新此列表。
我希望客户端 B 在调用 IncrementList() 时收到通知,以便它可以再次调用 GetList() 以显示更新的数据。

您能否概述一下您将如何实现这一点?回调?复式?发布者/订阅者?
WCF 4.0 中有什么新功能可以帮助解决这种情况吗?

服务图

谢谢!

I have one WCF service that exposes two operations - IncrementList() and GetList(). Client B connects to the service, calls GetList() and displays to the user. Client A has the ability to update this list by calling IncrementList().
I want Client B to get notified when IncrementList() is called so it can call GetList() again to display the updated data.

Could you please outline how you'd implement this? CallBacks? Duplex? Publisher/Subscriber?

Anything new in WCF 4.0 that aids in this scenario?

Service diagram

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌吟 2024-12-20 13:36:11

您应该预先决定的是,如果您想要在增量(重)时将整个列表推送到每个客户端,还是仅将更新的项目推送到每个客户端。下面的代码用于推送整个列表,但很容易修改它只是为了推送更新的对象(推荐)。
在应用程序启动时,客户端 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 的实现应该执行回调以推送新列表(或更好的是添加到列表中的新对象)到客户端 - 类似:

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)

Something you should decide up front is if you want to push the whole list when its incremented (heavy) or just the updated item to each client. The code below is for push whole list but easy to modify this just to push the updated object (recomended).
At app start Client B should call Register_client and then GetList. Subsequently it will be notified via call back when list is incremented (the client needs to implient this interface)
The call GetList requires a duplex channel and SessionMode.Required.

Your server should impliment:

[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]...
}

Your client should impliment:

public interface IMyCallback {
    [OperationContract(IsOneWay = true)]
    void PushList(ListObject[] list);
}

Register client just needs store client callback interface for use when list is incremented something like:

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));
}

Where:

private List<IMyCallback> clients = new List<IMyCallback>();

The impliementation of IncrementList should do a callback to push new list (or better just the new object that was added to list) to client - something like:

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));
    }
}

The callback implimentation (client side) looks something like:

public class MyCallback : IMyCallback {
public void PushList(ListObject[] list) {
    // Were client side - update list code here...
}

Probably this callback implimentation needs a reference to some object that holds the list data - probably this is passed in to contructor (not shown).

When you instantiate your proxy object you will need to pass an instance of callback to the proxy constructor - something like:

MyServerClient client_proxy = new MyServerClient(new InstanceContext(my_callback, binding_str)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文