SignalR + Autofac + OWIN:为什么GlobalHost.ConnectionManager.GetHubContext不起作用?

时间:2014-01-15 00:02:08

标签: asp.net signalr autofac owin

我正在尝试在单个项目中使用OWIN,SignalR和Autofac。

我正在设置有关signalR的内容如下:

       // Create the AutoFac container builder:
        var builder = new ContainerBuilder();

        // ...[Register various other things in here]...

        // register signalR Hubs
        builder.RegisterHubs(Assembly.GetExecutingAssembly());

        // Build the container:
        var container = builder.Build();

        // Configure SignalR with the dependency resolver.
        app.MapSignalR(new HubConfiguration
        {
            Resolver =  new AutofacDependencyResolver(container)
        });

我的问题是,当我使用Autofac SignalR集成时,我无法再在服务器上获取signalR Hub Context(例如在webapi控制器中),因此无法从服务器端向连接的客户端发送消息。当我没有使用Autofac signalR集成时,如下所示:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
hubContext.Clients.All.notification("Test Message");

但是当我将Autofac添加到混合中时,这不起作用 - 我没有得到任何错误消息,我似乎得到了一个hubContext,但是对它的调用实际上似乎并没有到达客户端。 / p>

如果我在对MapSignalR的调用中注释掉了对signalR的依赖性解析器的使用,对GetHubContext的调用再次起作用,消息成功地到达signalR客户端,但当然我不能再在我的集线器上使用IoC。 e.g。

        // Configure SignalR with the dependency resolver.
        app.MapSignalR(new HubConfiguration
        {
            // Resolver =  new AutofacDependencyResolver(container)
        });

有人可以告诉我为什么使用AutofacDependencyResolver会阻止GlobalHost.ConnectionManager.GetHubContext正常工作吗?

注意:我尝试的另一件事是代替使用GlobalHost.ConnectionManager.GetHubContext()我尝试将一个IConnectionManager注入webapi控制器,我想从中向客户端发送消息,然后调用GetHubContext,但Autofac无法解析IConnectionManager。

我确实找到了Piotr Szmyd的以下文章,显然允许这样:

http://www.szmyd.com.pl/blog/wiring-signalr-with-autofac

但这似乎是基于过时的signalR构建,虽然这里似乎有一个nuget包:

http://www.nuget.org/packages/SignalR.AutoFac/

它似乎也已经过时了。

3 个答案:

答案 0 :(得分:32)

如果您使用SignalR的自定义依赖项解析程序,除非您修改它,否则不能再使用GlobalHost

GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();

// A custom HubConfiguration is now unnecessary, since MapSignalR will
// use the resolver from GlobalHost by default.
app.MapSignalR();

如果您不想修改GlobalHost,则必须手动解析IConnectionManager:

IDependencyResolver resolver = new AutofacDependencyResolver(container);
IHubContext hubContext = resolver.Resolve<IConnectionManager>().GetHubContext<MyHub>();

app.MapSignalR(new HubConfiguration
{
    Resolver = resolver
});

答案 1 :(得分:2)

对于SignalR,Autofac和OWIN的完整答案,我做了以下工作:

// register IPersistantConnectionContext for access to SignalR connection
// and IDependencyResolver to enable inection of the container into its
// construction for the config object.
var builder = new ContainerBuilder();
builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
    .As<IDependencyResolver>()
    .SingleInstance();
builder.Register((context, p) =>
        context.Resolve<IDependencyResolver>()
            .Resolve<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>()
            .GetConnectionContext<SignalRConnection>());

// ... other registrations

var container = builder.Build();

var signalrConfiguration = new ConnectionConfiguration
{
    Resolver = container.Resolve<IDependencyResolver>(),
};

app.UseAutofacMiddleware(container);

app.MapSignalR<SignalRConnection>("/signalr", signalrConfiguration);

// ... other middleware

在我的控制器中,我包含了IPersistentConnectionContext类型的参数,并注入了正确的实例。

我使用的是PersistentConnection,但它与Hubs类似。

答案 2 :(得分:-1)

为了扩展Nathan的答案,我正在使用与关键线

类似的东西
builder.RegisterHubs(Assembly.GetExecutingAssembly()).SingleInstance();

在Startup.cs。

该行&#34; SingleInstance()&#34;确保只有一个&#34;实例&#34;整个应用程序使用集线器。

然后我只是在控制器的构造函数中使用简单的依赖注入来获取指向集线器的指针。