SignalR在同一应用中的不同路径上有多个集线器?

时间:2013-08-27 12:51:07

标签: c# signalr

我的应用程序在唯一路径上包含多个集线器,因此在调用默认值时:

routes.MapHubs("path", new HubConfiguration(...));

它爆炸说已经定义了signalr.hubs(如MapHubs not needed in SignalR 1.01?所述)。

现在我可以理解它应该只被调用一次,但是你只能获得1个路径,那么有没有办法处理每个集线器场景的路径?喜欢如何使用MVC指定控制器和动作?所以像:

routes.MapHub<SomeHub>("path", new HubConfiguration(...));

==编辑更多信息==

经常提到你应该永远不需要多次调用这个地图集线器,并且在大多数场景中我可以同意,但是我不会说这将是所有申请。

在这种情况下,它是一个网站,在运行时加载任何可用的插件,每个插件都公开依赖注入框架以包含其依赖项和路由表以包含其路由。集线器可能彼此无关(除了它们都是集线器对象的事实)。因此,集线器并非都是预先知道的,只有在插件加载后才会知道,是的,我可以等到此之后再尝试将集线器绑定在那里,然而如何为每个集线器设置自定义路由呢?

这似乎是SignalR试图抽象一点太多的情况,因为我不认为拥有自定义路线而不是默认&#34; / signalr&#34;并且作为路线是一个坏主意所有人都有不同的责任,对他们来说都有一条入境路线似乎很糟糕。

所以无论如何我认为问题仍然存在,因为我不认为这是一个糟糕的用例或糟糕的设计,它似乎只是我希望能够有一个应用集线器的路由,非常像在mvc中,您将控制器和操作应用于路径。

1 个答案:

答案 0 :(得分:2)

您不需要超过signalr.hubs路线。如果您将浏览器指向该路由,您将看到它自动查找可分配给IHub的所有公共类型,并为它们创建JavaScript代理。您可以通过JavaScript的名称与不同的集线器进行交互,即如果您有以下集线器:

public class GameHub : Hub

您可以通过执行以下操作连接到该特定中心:

var gameHubProxy = $.connection.gameHub;

您还可以通过将HubNameAttribute添加到班级中来明确指定中心名称:

[HubName("AwesomeHub")]
public class GameHub : Hub

然后,您可以通过执行

来检索特定代理
var awesomeHubProxy = $.connection.awesomeHub;

<强>更新

我不确定SignalR是否能够在同一个应用程序中的多个路径上运行。它可能会搞砸了,默认的程序集定位器无法选择在运行时加载的集线器。

但是,有一个解决方案,您可以实现自己的IAssemblyLocator,它将从您的插件程序集中选择集线器:

public class PluginAssemblyLocator : DefaultAssemblyLocator
{
    private readonly IEnumerable<Assembly> _pluginAssemblies;

    public PluginAssemblyLocator(IEnumerable<Assembly> pluginAssemblies)
    {
        _pluginAssemblies = pluginAssemblies;
    }

    public override IList<Assembly> GetAssemblies()
    {
        return base.GetAssemblies().Union(_pluginAssemblies).ToList();
    }
}

加载插件后,应致电MapHubs并注册SignalRs IAssemblyLocator服务的覆盖:

protected void Application_Start(object sender, EventArgs e)
{
    // Load plugins and let them specify their own routes (but not for hubs).
    var pluginAssemblies = LoadPlugins(RouteTable.Routes);

    RouteTable.Routes.MapHubs();

    GlobalHost.DependencyResolver.Register(typeof(IAssemblyLocator), () => new PluginAssemblyLocator(pluginAssemblies));
}

注意:注册您IAssemblyLocator之后的MapHubs ,因为它也会覆盖它。

现在,这种方法存在 问题。如果您正在使用静态JavaScript代理,则每次访问时都不会重新生成它。这意味着如果在加载所有插件/集线器之前访问了您的/signalr/hubs代理,则不会获取它们。您可以通过确保在映射路由时或者根本不使用静态代理来加载所有集线器来解决此问题。

此解决方案仍然需要您获得对插件程序集的引用,我希望这是可行的......