Resolving instances with ASP.NET Core DI
如何使用ASP.NET Core MVC内置依赖注入框架手动解析类型?
设置容器很容易:
1 2 3 4 5 6 | public void ConfigureServices(IServiceCollection services) { // ... services.AddTransient<ISomeService, SomeConcreteService>(); } |
但是如何在不执行注射的情况下解析
1 | ISomeService service = services.Resolve<ISomeService>(); |
1 |
还有一些便利扩展方法可用,例如
解析启动类中的服务
注入依赖项
运行时可以在
也可以在
1 2 3 4 | public void Configure(IApplicationBuilder app, IFooService fooService) { // ... } |
但是
1 2 3 4 5 6 7 8 9 10 11 | public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { // Use Configuration here } |
手动解决依赖关系
如果要手动解析服务,可以让运行时在构造函数中注入
1 2 3 4 | public Startup(IServiceProvider serviceProvider) { var hostingEnv = serviceProvider.GetService<IHostingEnvironment>(); } |
要么
1 2 3 4 5 | public void Configure(IApplicationBuilder app) { var serviceProvider = app.ApplicationServices; var hostingEnv = serviceProvider.GetService<IHostingEnvironment>(); } |
但是,如果需要在
1 2 3 4 5 6 7 8 | public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IFooService, FooService>(); // Build the intermediate service provider var sp = services.BuildServiceProvider(); var fooService = sp.GetService<IFooService>(); } |
你需要
请注意:
通常,您不应解析
1 2 3 4 5 | public void ConfigureServices(IServiceCollection services) { var myOptions = new MyOptions(); Configuration.GetSection("SomeSection").Bind(myOptions); } |
手动解析服务(也称为服务定位器)通常被称为反模式。虽然它有用例(对于框架和/或基础架构层),但您应该尽可能地避免使用它。
手动解析实例涉及使用
解决Startup.ConfigureServices中的依赖关系
1 2 3 4 5 6 7 | public void ConfigureServices(IServiceCollection services) { services.AddTransient<IMyService, MyService>(); var serviceProvider = services.BuildServiceProvider(); var service = serviceProvider.GetService<IMyService>(); } |
解决Startup.Configure中的依赖项
1 2 3 4 5 6 7 8 9 10 11 12 | public void Configure( IApplicationBuilder application, IServiceProvider serviceProvider) { // By type. var service1 = (MyService)serviceProvider.GetService(typeof(MyService)); // Using extension method. var service2 = serviceProvider.GetService<MyService>(); // ... } |
使用运行时注入服务
某些类型可以作为方法参数注入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class Startup { public Startup( IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory) { } public void ConfigureServices( IServiceCollection services) { } public void Configure( IApplicationBuilder application, IHostingEnvironment hostingEnvironment, IServiceProvider serviceProvider, ILoggerFactory loggerfactory, IApplicationLifetime applicationLifetime) { } } |
解决控制器操作中的依赖关系
1 2 | [HttpGet("/some-action")] public string SomeAction([FromServices] IMyService myService) =>"Hello"; |
如果您使用模板生成应用程序,那么您将在
1 2 3 4 5 6 7 | public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddApplicationInsightsTelemetry(Configuration); services.AddMvc(); } |
然后,您可以在那里添加依赖项,例如:
1 | services.AddTransient<ITestService, TestService>(); |
如果要在控制器上访问
1 | public HomeController(IServiceProvider serviceProvider) |
然后,您可以解决您添加的服务:
1 | var service = serviceProvider.GetService<ITestService>(); |
请注意,要使用通用版本,您必须包含带有扩展名的命名空间:
1 | using Microsoft.Extensions.DependencyInjection; |
ITestService.cs
1 2 3 4 | public interface ITestService { int GenerateRandom(); } |
TestService.cs
1 2 3 4 5 6 7 | public class TestService : ITestService { public int GenerateRandom() { return 4; } } |
Startup.cs(ConfigureServices)
1 2 3 4 5 6 7 | public void ConfigureServices(IServiceCollection services) { services.AddApplicationInsightsTelemetry(Configuration); services.AddMvc(); services.AddTransient<ITestService, TestService>(); } |
HomeController.cs
1 2 3 4 5 6 7 8 9 10 11 | using Microsoft.Extensions.DependencyInjection; namespace Core.Controllers { public class HomeController : Controller { public HomeController(IServiceProvider serviceProvider) { var service = serviceProvider.GetService<ITestService>(); int rnd = service.GenerateRandom(); } |
如果您只需要解析一个依赖项以将其传递给您正在注册的另一个依赖项的构造函数,则可以执行此操作。
假设您有一个接受字符串和ISomeService的服务。
1 2 3 4 5 6 7 | public class AnotherService : IAnotherService { public AnotherService(ISomeService someService, string serviceUrl) { ... } } |
当你在Startup.cs中注册这个时,你需要这样做:
1 2 3 | services.AddScoped<IAnotherService>(ctx => new AnotherService(ctx.GetService<ISomeService>(),"https://someservice.com/") ); |
您可以通过这种方式在AuthorizeAttribute等属性中注入依赖项
1 | var someservice = (ISomeService)context.HttpContext.RequestServices.GetService(typeof(ISomeService)); |
1 2 3 4 5 6 7 8 9 10 | public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDbContext<ConfigurationRepository>(options => options.UseSqlServer(Configuration.GetConnectionString("SqlConnectionString"))); services.AddScoped<IConfigurationBL, ConfigurationBL>(); services.AddScoped<IConfigurationRepository, ConfigurationRepository>(); } |