繁体   English   中英

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

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

我目前正在构建一个服务器应用程序,该应用程序通过TCP传递自定义协议。 该服务器应用程序当前使用Autofac进行依赖项注入。

不过,最近,我在解决方案中添加了一个ASP.NET Core项目,以提供用于运行服务器应用程序的HTTP API,主要用于提供管理Web应用程序。

Autofac为ASP.NET Core项目提供了集成,但是我很难弄清楚如何告诉ASP.NET Core服务配置使用已经构建的Autofac服务容器,以便我的TCP服务和HTTP API可以从同一容器解析服务。

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 ━━━━┛
}

该示例仅显示了如何从头开始为ASP.NET Core应用程序构建完整的容器,但是现在如何重用现有容器。

IWebHostBuilder上无法使用ConfigureServices方法,因为该方法的返回类型为void ,所以我无法在AutofacServiceProvider返回AutofacServiceProvider

这是我启动应用程序的方式:

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();
    }
}

那么,如何使用同一个容器来解析TCP服务器和HTTP API中的依赖关系?

谢谢!

我相信您应该能够用Autofac容器替换默认的(内置)asp.net核心容器。 在这种情况下,Startup.ConfigureServices必须返回IServiceProvider(而不是void)。

请参阅本文档中的“默认服务容器替换”部分 相关部分位于页面末尾。 您应该能够适应您的情况。

希望这对您有用。 如果是这样,请将其标记为答案。

您还可以尝试提供一个聚合的服务提供者,类似于此处提供的服务提供者( 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();
    }
}

然后,将配置服务中的代码更改为:

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

缺点是来自ASP.NET Core的服务将不能用于您的Autofac容器,但是,正如我所看到的,这对您来说应该不是问题。

暂无
暂无

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

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