2

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

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

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

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

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

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

经常提到您永远不需要多次调用此地图中心,并且在大多数情况下我同意,但是我不会说所有应用程序都会如此。

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

这似乎是 SignalR 试图抽象太多的情况,因为我认为拥有自定义路由而不是默认的“/signalr”并不是一个坏主意,并且由于路由都有不同的职责,因此似乎不好他们都有一条进入路线。

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

4

1 回答 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;

更新:

我不确定 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并注册 SignalRsIAssemblyLocator服务的覆盖:

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 AFTERMapHubs ,因为它也会覆盖它。

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

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

于 2013-08-27T13:13:50.760 回答