代码之家  ›  专栏  ›  技术社区  ›  Grofit

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

  •  2
  • Grofit  · 技术社区  · 11 年前

    我有一个应用程序,它包含多个集线器,所有集线器都在唯一的路径上,所以当调用默认值时:

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

    它爆炸了,说信号中枢已经定义好了(如这里所述 MapHubs not needed in SignalR 1.01? ).

    现在我可以理解它只应该被调用一次,但那时你只会得到一个路径,所以有什么方法可以处理每个集线器的路径场景吗?比如MVC如何指定控制器和操作?所以类似于:

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

    ==编辑以获取更多信息==

    人们经常提到,您永远不需要多次调用此地图中心,并且 场景我可以同意,但我不会说所有应用程序都是这样。

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

    这似乎是SignalR试图抽象得有点太多的情况,因为我认为拥有自定义路线而不是默认的“/signer”不是一个坏主意,而且由于路线都有不同的责任,所以为所有路线都有一条进入路线似乎很糟糕。

    所以不管怎样,我认为问题仍然存在,因为我不认为这是一个糟糕的用例或糟糕的设计,我只是希望能够有一个应用了集线器的路由,就像在mvc中,你将控制器和操作应用于路由一样。

    1 回复  |  直到 8 年前
        1
  •  2
  •   khellang    11 年前

    你不应该只需要 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的超控 I部件定位器 服务:

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

    注意: 注册 I部件定位器 之后 你打过电话 地图中心 因为它也会覆盖它。

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

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