[ASP.NET Core]在ASP.NET Core(.NET Core 3.1)的应用程序编程开发中如何获取依赖注入的服务的实例?
2.72K 次浏览
由于微软不再支持.NET Core 2.0的升级和更新,所以需要将一个基于.NET Core 2的项目升级到ASP.NET Core 3,但在升级过程中,遇到了一些问题,其中一个是需要在Program.cs
文件中获取一个服务的实例,在.NET Core 2中是通过BuildWebHost
来获取的,示例如下:
public class Program {
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<GameStoreContext>();
var configuration = services.GetRequiredService<IConfiguration>();
var userManager = services.GetRequiredService<UserManager<IdentityUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
DbInitializer.Initialize(context, configuration, userManager,roleManager).GetAwaiter().GetResult();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseContentRoot(Directory.GetCurrentDirectory())
.Build();
}
但在.NET Core 3.1中BuildWebHost
不再可用,因此无法通过以上方法获取到已注册的服务实例。那么,在.NET Core 3.1中应该如何获取依赖注入的服务的实例呢?
2 个回答
-
在.NET Core 3.1中,提供了IHost接口,可以使用IHost的静态扩展方法来实现,然后调用
IHost.Services.CreateScope()
方法获取服务的域,最后通过scope.ServiceProvider
属性获取到注册的服务集合,类似如下:public static IHost MigrateDbContext<TContext>(this IHost host) where TContext : DbContext { using (var scope = host.Services.CreateScope()) { var services = scope.ServiceProvider; var logger = services.GetRequiredService<ILogger<TContext>>(); // 获取数据库上下文 var context = services.GetService<TContext>(); // 你的业务逻辑 context.Database.Migrate(); } return host; }
然后在
Program.cs
文件中调用以上编写的IHost
的静态扩展方法,如下:public static void Main(string[] args) { CreateHostBuilder(args) .Build() .MigrateDbContext<WikiDbContext>() // 调用静态扩展方法 .Run(); } public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>()); }
-
如果不想创建静态扩展方法而保持原来的代码结构,那么你还可以调用
CreateHostBuilder(args).Build()
,然后调用host.Services.CreateScope()
方法获得服务域,如下:public static void Main(string[] args) { var host = CreateHostBuilder(args).Build(); using( var scope = host.Services.CreateScope() ) { var services = scope.ServiceProvider; try { var context = services.GetRequiredService<GameStoreContext>(); var configuration = services.GetRequiredService<IConfiguration>(); var userManager = services.GetRequiredService<UserManager<IdentityUser>>(); var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>(); DbInitializer.Initialize(context, configuration, userManager, roleManager).GetAwaiter().GetResult(); } catch( Exception ex ) { var logger = services.GetRequiredService<ILogger<Program>>(); } } host.Run(); }