首页 文章

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

提问于
浏览
2

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

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

它爆炸说已经定义了signalr.hubs(如这里提到的MapHubs not needed in SignalR 1.01?) .

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

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

==编辑更多信息==

经常提到你不应该多次调用这个 Map 集线器,并且在大多数情况下我都同意,但是我不会说所有应用都会出现这种情况 .

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

这似乎是SignalR尝试抽象一点太多的情况,因为我不认为拥有自定义路线而不是默认的“/ signalr”是一个坏主意,并且因为路线都有不同的责任,所以看起来很糟糕他们都有一条入境路线 .

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

1 回答

  • 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;
    

    UPDATE:

    我不确定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));
    }
    

    NOTE: 在您调用 MapHubs 之后注册 IAssemblyLocator ,因为它也会覆盖它 .

    现在,这种方法存在问题 . 如果每次访问时都重新生成're using the static JavaScript proxy, it won' . 这意味着如果在加载所有插件/集线器之前访问了 /signalr/hubs 代理,则不会选择它们 . 您可以通过在映射路由时确保所有集线器都已加载或根本不使用静态代理来解决此问题 .

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

相关问题