简体   繁体   English

使用ASP.NET Core注册现有的Autofac容器

[英]Registering an existing Autofac container with ASP.NET Core

I'm currently building a server application that speaks a custom protocol over TCP. 我目前正在构建一个服务器应用程序,该应用程序通过TCP传递自定义协议。 This server application currently uses Autofac for dependency injection. 该服务器应用程序当前使用Autofac进行依赖项注入。

Recently though, I've added an ASP.NET Core project to the solution to provide an HTTP API on to op the server application, mostly to provide a management web application. 不过,最近,我在解决方案中添加了一个ASP.NET Core项目,以提供用于运行服务器应用程序的HTTP API,主要用于提供管理Web应用程序。

Autofac provides integration for ASP.NET Core projects, but I'm having difficulty figuring out how I can tell the ASP.NET Core service configuration to use the Autofac service container that I've already built, so that my TCP serve and HTTP API can resolve services from the same container. Autofac为ASP.NET Core项目提供了集成,但是我很难弄清楚如何告诉ASP.NET Core服务配置使用已经构建的Autofac服务容器,以便我的TCP服务和HTTP API可以从同一容器解析服务。

Autofac provides documentation for this: Autofac为此提供了文档:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // Add services to the collection.
    services.AddMvc();

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

    builder.Populate(services);
    builder.RegisterType<MyType>().As<IMyType>();
    this.ApplicationContainer = builder.Build();

    // Create the IServiceProvider based on the container.
    return new AutofacServiceProvider(this.ApplicationContainer);
    //                                                   ^
    // This is where I'd like to insert my container ━━━━┛
}

The example only shows how to build a complete container from scratch for an ASP.NET Core application, but now how to re-use an existing container. 该示例仅显示了如何从头开始为ASP.NET Core应用程序构建完整的容器,但是现在如何重用现有容器。

Using the ConfigureServices method on an IWebHostBuilder doesn't work here, because that has a return type of void , so I can't return an AutofacServiceProvider there. IWebHostBuilder上无法使用ConfigureServices方法,因为该方法的返回类型为void ,所以我无法在AutofacServiceProvider返回AutofacServiceProvider

Here's how I start up my application: 这是我启动应用程序的方式:

var containerBuilder = new ContainerBuilder();

// Here's where I register all my services
containerBuilder.RegisterModule(new ApplicationModule());
var container = containerBuilder.Build();

using (var scope = container.BeginLifetimeScope())
{

    var server = scope.Resolve<TcpServer>();

    var isService = args.Contains("--winservice");

    // Construct the HTTP API
    var builder = WebHost
        .CreateDefaultBuilder(args.Where(arg => arg != "--winservice").ToArray())
        .ConfigureServices(collection =>
        {
            // Not sure what to do here?
            // I can call `collection.AddAutofac` here, not sure what that does
        })
        .UseStartup<ApplicationAPI>();

    // Start the HTTP API
    if (isService)
    {
        // Run as a Win Service
        builder.Build().RunAsCustomService(server);
    }
    else
    {
        await server.Start();

        // Do not run as a Win Service
        builder.Build().Run();
    }
}

So how can I use the same container to resolve dependencies in both my TCP server and HTTP API? 那么,如何使用同一个容器来解析TCP服务器和HTTP API中的依赖关系?

Thanks! 谢谢!

I believe you should be able to replace the default (built-in) asp.net core container with your Autofac container. 我相信您应该能够用Autofac容器替换默认的(内置)asp.net核心容器。 In that case, Startup.ConfigureServices must return IServiceProvider (rather than void). 在这种情况下,Startup.ConfigureServices必须返回IServiceProvider(而不是void)。

Look at the "Default service container replacement" section in this documentation. 请参阅本文档中的“默认服务容器替换”部分 The relevant section is towards the end of the page. 相关部分位于页面末尾。 You should be able to adapt this to your situation. 您应该能够适应您的情况。

Hopefully this works for you. 希望这对您有用。 If it does, please mark this as the answer. 如果是这样,请将其标记为答案。

You could also try to provide an aggregated service provider, something like the one provided here ( https://github.com/kephas-software/kephas/blob/master/src/Kephas.Composition.DependencyInjection/Composition/DependencyInjection/AggregatedServiceProvider.cs ): 您还可以尝试提供一个聚合的服务提供者,类似于此处提供的服务提供者( https://github.com/kephas-software/kephas/blob/master/src/Kephas.Composition.DependencyInjection/Composition/DependencyInjection/AggregatedServiceProvider。 cs ):

/// <summary>
/// An aggregated service provider.
/// </summary>
public class AggregatedServiceProvider : IServiceProvider, IDisposable
{
    private readonly IList<IServiceProvider> innerServiceProviders;

    /// <summary>
    /// Initializes a new instance of the <see cref="AggregatedServiceProvider"/> class.
    /// </summary>
    /// <param name="innerServiceProviders">A variable-length parameters list containing inner
    ///                                     service providers.</param>
    public AggregatedServiceProvider(params IServiceProvider[] innerServiceProviders)
    {
        this.innerServiceProviders = innerServiceProviders.ToList();
    }

    /// <summary>
    /// Gets the service object of the specified type.
    /// </summary>
    /// <param name="serviceType">An object that specifies the type of service object to get.</param>
    /// <returns>
    /// A service object of type <paramref name="serviceType">serviceType</paramref>.   -or-  null if
    /// there is no service object of type <paramref name="serviceType">serviceType</paramref>.
    /// </returns>
    public object GetService(Type serviceType)
    {
        foreach (var serviceProvider in this.innerServiceProviders)
        {
            var service = serviceProvider.GetService(serviceType);
            if (service != null)
            {
                return service;
            }
        }

        return null;
    }

    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged
    /// resources.
    /// </summary>
    public void Dispose()
    {
        foreach (var serviceProvider in this.innerServiceProviders)
        {
            (serviceProvider as IDisposable)?.Dispose();
        }

        this.innerServiceProviders.Clear();
    }
}

Then, change the code you have in configure services to: 然后,将配置服务中的代码更改为:

return new AgregegatedServiceProvider(new ServiceProvider(services), myAutofacContainer);

The drawback is that the services from ASP.NET Core will not be available to your Autofac container, but, as I see, this should not be a problem for you. 缺点是来自ASP.NET Core的服务将不能用于您的Autofac容器,但是,正如我所看到的,这对您来说应该不是问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM