首页 / 问答 / [ASP.NET Core]在ASP.NET Core(.NET Core 3.1)的应用程序编程开发中如何获取依赖注入的服务的实例?

[ASP.NET Core]在ASP.NET Core(.NET Core 3.1)的应用程序编程开发中如何获取依赖注入的服务的实例?

0

由于微软不再支持.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 个回答

  • 1

    在.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>());
    }
    
    Rector的个人主页

    Rector

    2020-10-27 回答

    • 0

      如果不想创建静态扩展方法而保持原来的代码结构,那么你还可以调用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();
      }
      
      Rector的个人主页

      Rector

      2020-10-27 回答

      我来回答