WCF Duplex - 向每个客户端推送不同的通知?

Joh*_*ner 5 wcf push-notification

我正在设计一个我所有客户将连接的2 WCF服务.其中一项服务是通知服务.

我希望每个客户端连接到服务,订阅它,然后使用双工Callback接口接收通知(该服务将触发客户端中的'Notify'操作).

这是我的设计理念:

在此输入图像描述

我的问题是:当每个客户端连接到我的服务时,我将根据我的数据库中的"用户"表进行验证(我将使用UserNamePasswordValidator并实现'验证'功能).

要求:每个用户都需要根据数据库中定义的规则接收不同的通知,但它们都使用相同的合同.

例如:

约翰史密斯在数据库中的规则可能是:通知我所有价格超过100美元的新产品.

Jane Doe在数据库中的规则可能是:在所有名为"JA"的新产品上通知我.

吉姆贾布拉在数据库中的规则可能是:通知我所有"食品"类型的新产品.

我的服务将有一个工作线程,用于检测数据库中的更改(新产品已插入数据库).

然后它应该遍历所有连接的客户端 - 并且每个客户端只有在与客户端的通知请求匹配时才向他发送新产品的通知.

同样 - 所有客户端都会收到相同类型的更新(新产品),但每个客户端应根据数据库中的规则接收不同的产品.

我认为实现这一点的一种方法是使用Singleton服务,该服务包含以下列表:

  • 客户端Enpoint
  • 用户对象(来自数据库)

这样 - 每次工作线程检测到新产品时,它都会遍历此列表并向需要它的人发送通知.这种方法的问题在于,为了拥有一个全球客户列表 - 我需要将服务作为Singlton,对吧?

第二种方法是......好吧......我不知道如何从工作线程访问连接到服务的客户端列表......

我想我遇到的主要问题是每个客户都可能想要通知他不同类型的产品.含义 - pub\sub方法在这里不太好,因为我的场景要求服务了解客户端.

关于如何解决这个令人头疼的问题的任何建议?

Ale*_*sev 2

无论以何种方式进行双工通信,您都需要维护从服务器到客户端打开的 TCP 通道,以便能够发送通知。

客户端是发起到服务器的连接的人,你需要保持此连接打开,如果此连接丢失,你不能(不应该)发起从服务器到客户端的连接,因为客户端可能位于 NAT 之后,有防火墙, ETC。

因此,无论如何,服务器端必须有一些静态(单例)对象来保存客户端连接列表,尽管这不一定是 WCF 服务。您可以将此对象依赖注入到服务构造函数中。

public class ProductRepository
{
    private EventAggregator eventAggregator;

    public void Add(Product product)
    {
        //...
        eventAggregator.Publish(new NewProductEvent(product))
    }
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class EventPublishingService
{
    private IClientCallback client;
    private EventAggregator eventAggregator;
    private Func<Product, bool> predicate;

    public EventPublishingService(...)
    {
        eventAggregator.Subscibe<NewProductEvent>(OnNewProduct);
    }
    private void OnNewProduct(NewProductEvent e)
    {
        if (predicate(e.Product)==true) client.Notify(e.Product);
    }

    public void Subscribe()
    {
        client = OperationContext.Current.GetCallbackChannel<IClientCallback>()
        var user = ServiceSecurityContext.PrimaryIdentity;
        predicate = GetFilterForUser(user);
    }
}
Run Code Online (Sandbox Code Playgroud)