谁以及如何在依赖注入中初始化接口



对于 Asp.Net 核心依赖注入,我知道我们将依赖性注册到IServiceCollection中,并使用IServiceProvider来获取实例。

我想知道注册和初始化IServiceCollection的代码。

对于接口注入,为什么它知道从服务集合中获取实例?哪个代码实现此功能?

我想知道全局控制器是谁以及如何控制它?

创建 ASP.NET Core 项目时,会为Program.Main()生成以下代码:

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }
    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

IServiceCollection 的实例在 WebHost.CreateDefaultBuilder(args) 中创建,然后传递给Startup.ConfigureServices(IServiceCollection services)调用。

如果你想跟踪 ASP.NET 核心源代码中的调用链,这里是(包括指向github上的源代码的链接(:

WebHost.CreateDefaultBuilder(( 调用WebHostBuilderExtensions.UseDefaultServiceProvider()扩展方法:

public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new WebHostBuilder()
        .UseIISIntegration()
        // ...
        .UseDefaultServiceProvider((context, options) =>
        {
            options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
        });
        // ...
    return builder;
}

WebHostBuilderExtensions.UseDefaultServiceProvider(( 调用WebHostBuilder.ConfigureServices()方法:

public static IWebHostBuilder UseDefaultServiceProvider(this IWebHostBuilder hostBuilder, Action<WebHostBuilderContext, ServiceProviderOptions> configure)
{
    return hostBuilder.ConfigureServices((context, services) =>
    {
        var options = new ServiceProviderOptions();
        configure(context, options);
        services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IServiceCollection>>(new DefaultServiceProviderFactory(options)));
    });
}

WebHostBuilder最终会创建ServiceCollection的实例并调用Startup.ConfigureServices()方法(通过存储操作(:

private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
{
    //  ...
    // Creation of `ServiceCollection` instance
    var services = new ServiceCollection();
    //  ...
    foreach (var configureServices in _configureServicesDelegates)
    {
        configureServices(_context, services);
    }
    //  ...
}

为了补充已经提供的答案,在 asp.net 核之外,DI 框架可以单独单独使用,因为它是一个完全解耦的模块。

基本 .NET - 使用 .NET Core 的依赖关系注入

public static void Main() {
    IServiceCollection serviceCollection = new ServiceCollection();
    ConfigureServices(serviceCollection);
    var application = new MyApplication(serviceCollection);
    // Run
    // ...
}
static private void ConfigureServices(IServiceCollection services) {
    ILoggerFactory loggerFactory = new Logging.LoggerFactory();
    services.AddInstance<ILoggerFactory>(loggerFactory);
    //...
}

唯一的区别是,现在您必须自己创建集合,而不是框架作为其管道的一部分为您执行此操作。

从评论中,

值得一提的是,ASP.NET Core应用程序只不过是一个控制台应用程序,因此解释了为什么您也可以在基本的控制台应用程序中使用IServiceColleciton,或者您喜欢的其他任何地方。

这是我在 .net core 2.2 上的做法:

using System;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleAppDependencyInjection
{
    class Program
    {
        static void Main(string[] args)
        {
            var serviceProvider = ConfigureContainer();
            var service1 = serviceProvider.GetService<Service1>();
            var service2 = serviceProvider.GetService<Service2>();
            Debug.Assert(service1 != null);
            Debug.Assert(service2 != null);
        }
        static IServiceProvider ConfigureContainer()
        {
            var services = new ServiceCollection();
            ConfigureServices(services);
            return services.BuildServiceProvider();
        }
        static void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<Service1>();
            services.AddSingleton<Service2>();
        }
    }
    public class Service1
    {
        public Service1()
        {
        }
    }
    public class Service2
    {
        Service1 service1;
        public Service2(Service1 service1)
        {
            this.service1 = service1;
        }
    }
}

最新更新