如何在 MVC 5 应用程序中配置 Autofac 和 SignalR

How to configure Autofac and SignalR in a MVC 5 application

我正在尝试配置 MVC 5 应用程序以使用 SignalR 2。2.x 并将服务注入我的 NotificationsHub。 我们正在为 MVC 使用 Autofac,但我不确定如何正确配置它。 NuGet Autofac.Integration.SignalR (3.0.2)Autofac.Integration.Mvc (3.3.4).

存在 Autofac 文档

到目前为止我正在做的是通过以下方式注册集线器:

ContainerBuilder builder = new ContainerBuilder();

// Register MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);

builder.RegisterType<ServiceForSignalRHub>().AsImplementedInterfaces();
builder.RegisterType<...>().AsImplementedInterfaces();

builder.RegisterHubs(Assembly.GetExecutingAssembly());

IContainer container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

然而,对 .SetResolver(...) 的调用是不明确的,因为它存在于 MVC 和 SignalR 集成包中。怎么办?我无法确认我的服务的构造函数注入是否适用于我正在使用的集线器。

编辑

我可以用 Autofac 配置 MVC5 就好了。我迷路的地方是如何使用 Autofac 信号集成 NuGet 对 SignalR 执行相同的操作。 请看下面

这是我的创业公司class:

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var defaultFactory = LogManager.Use<DefaultFactory>();
        defaultFactory.Directory("@D:\NServiceBus\ );
        defaultFactory.Level(LogLevel.Debug);

        var container = ConfigureAutofac(app);

        ConfigureServiceBus(container, app);

        app.UseAutofacMiddleware(container); // REGISTER WITH OWIN
        app.UseAutofacMvc();

        ConfigureAuth(app);

        GlobalConfiguration.Configuration.UseSqlServerStorage("hangfire");

        ConfigureSignalR(app);
    }
}

这是我配置 SignalR 的部分:

public partial class Startup
{
    public void ConfigureSignalR(IAppBuilder app)
    {
        var builder = new ContainerBuilder();

        builder.RegisterHubs(Assembly.GetExecutingAssembly()).PropertiesAutowired();
        builder.RegisterType<MaintenanceService>().As<IMaintenanceService>().PropertiesAutowired();

        var container = builder.Build();
        //var container = new AutofacContainer().Container;

        var resolver = new AutofacDependencyResolver(container);

        // Any connection or hub wire up and configuration should go here
        app.MapSignalR(new HubConfiguration
        {
            Resolver = resolver,
            EnableJSONP = true,
            EnableDetailedErrors = true,
            EnableJavaScriptProxies = true
        });

        builder.RegisterInstance(resolver.Resolve<IConnectionManager>());
    }
}

如何才能正确做到这一点?

您应该在映射时明确告诉 SignalR 使用 AutofacDependencyResolver。 我假设您知道在 Startup class 中您必须调用 app.MapSignalR();

当你映射它时,你应该告诉它使用自定义依赖解析器(AutofacDependencyResolver)。

这是我的做法:

var resolver = new AutofacDependencyResolver(container);

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

这样,您就可以直接告诉 SignalR 使用哪个依赖项解析器。

我有一个 GitHub repo for SignalR Dependency Injection,但它没有配置为使用 MVC。不过,我认为它会给您提示如何创建您的配置。

注意:如果您使用的是 OWIN 中间件,请确保根本不要使用 GlobalHost static 属性,因为它会产生大量的不一致。

A common error in OWIN integration is use of the GlobalHost. In OWIN you create the configuration from scratch. You should not reference GlobalHost anywhere when using the OWIN integration.

再次检查我给你的 repo,看看如何做到这一点。

希望这对您有所帮助:) 祝你好运!

我最终得到了这个(注意评论):

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);

        IContainer container = AutofacConfig(app);
        app.UseAutofacMiddleware(container);
        app.UseAutofacMvc();
        DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(container));
        GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        app.UseAutofacWebApi(GlobalConfiguration.Configuration);

        var hubConfiguration = new Microsoft.AspNet.SignalR.HubConfiguration()
        {
            // Resolve presolver from container
            Resolver = container.Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>(),
        };
        app.MapSignalR(hubConfiguration);

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

_

private static IContainer AutofacConfig(IAppBuilder app)
{
    var builder = new ContainerBuilder();

    RegisterSignalR(builder);

    return builder.Build();
}

_

private static void RegisterSignalR(ContainerBuilder builder)
{
    // Register Autofac resolver into container to be set into HubConfiguration later
    builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
           .As<Microsoft.AspNet.SignalR.IDependencyResolver>()
           .SingleInstance();

    // Register ConnectionManager as IConnectionManager so that you can get
    // hub context via IConnectionManager injected to your service
    builder.RegisterType<Microsoft.AspNet.SignalR.Infrastructure.ConnectionManager>()
           .As<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>()
           .SingleInstance();

    // Register hubs one by one
    builder.RegisterType<MessageNotificationsHub>().ExternallyOwned();
    builder.RegisterType<SystemNotificationsHub>().ExternallyOwned();
}

感谢@Nathan 和 his answer (originally found here) 以及逻辑思维来弄清楚将 ConnectionManager 注册为 IConnectionManager

安装 nuget 包 Autofac.SignalR,例如:

<package id="Autofac.SignalR" version="3.0.2" targetFramework="net471" />

注册您的集线器

// during creation of the IContainer, register signalr hubs automatically
var executingAssembly = Assembly.GetExecutingAssembly();
builder.RegisterHubs(executingAssembly);

// alternatively register hubs individually
// ExternallyOwned() ensures SignalR is allowed to control disposal of the hubs rather than Autofac.
builder.RegisterType<NotificationHub>().ExternallyOwned();

设置信号器服务定位器

// replace the Signalr dependency resolver once your IContainer 'container' is ready
GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);

// or this can alternatively be set in the HubConfiguration instance when using OWIN IAppBuilder map.RunSignalR(hubConfiguration);
var hubConfiguration = new HubConfiguration
{
    Resolver = new AutofacDependencyResolver(container),
    //...
}

更多信息:

https://autofaccn.readthedocs.io/en/latest/integration/signalr.html

https://docs.microsoft.com/en-us/aspnet/signalr/overview/advanced/dependency-injection