对于 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;
}
}
}