代码之家  ›  专栏  ›  技术社区  ›  Bernard

ASP.NET核心内的依赖项注入

  •  0
  • Bernard  · 技术社区  · 6 年前

    一直在用ASP.NET核心做一些示例代码,试图理解它是如何组合在一起的,我很难理解为什么我无法成功地解析服务。

    configure services方法具有添加ISeedDataService的调用

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOptions();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    
        services.AddDbContext<CustomerDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    
        services.AddScoped<ICustomerDbContext, CustomerDbContext>();
        services.AddScoped<ICustomerRepository, CustomerRepository>();
        services.AddScoped<ISeedDataService, SeedDataService>();
    }
    

    在配置中,我调用addseedata(),如下所示

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
       app.AddSeedData();
    }
    

    调用下面的扩展方法

    public static async void AddSeedData(this IApplicationBuilder app)
    {
        var seedDataService = app.ApplicationServices.GetRequiredService<ISeedDataService>();
        await seedDataService.EnsureSeedData();
    }
    

    SeedDataService在下面

    public class SeedDataService : ISeedDataService
    {
        private ICustomerDbContext _context;
        public SeedDataService(ICustomerDbContext context)
        {
            _context = context;
        }
    
        public async Task EnsureSeedData()
        {
            _context.Database.EnsureCreated();
    
            _context.Customers.RemoveRange(_context.Customers);
            _context.SaveChanges();
    
            Customer customer = new Customer();
            customer.FirstName = "Chuck";
            customer.LastName = "Norris";
            customer.Age = 30;
            customer.Id = Guid.NewGuid();
    
            _context.Add(customer);
    
            Customer customer2 = new Customer();
            customer2.FirstName = "Fabian";
            customer2.LastName = "Gosebrink";
            customer2.Age = 31;
            customer2.Id = Guid.NewGuid();
    
            _context.Add(customer2);
    
            await _context.SaveChangesAsync();
        }
    }
    

    完全不确定我做错了什么,错误是 System.InvalidOperationException:“无法从根提供程序解析作用域服务”secondapp.services.isedDataService“。”

    2 回复  |  直到 6 年前
        1
  •  2
  •   Henk Mollema    6 年前

    您正在(并且应该)添加 ISeedDataService 作为作用域服务。但是,您正在尝试从 根服务提供程序 (例如) app.ApplicationServices )不在范围内。这意味着从中有效解析的作用域服务将变成单实例服务,并且在应用程序关闭之前不会被释放,否则将导致错误。

    这里的解决方案是自己创建一个范围:

    public void Configure(IApplicationBuilder app)
    {
        using (var scope = app.ApplicationServices.CreateScope())
        {
            var seedDataService = scope.ServiceProvider.GetRequiredService<ISeedDataService>();
            // Use seedDataService here
        }
    }
    

    请看一下 at the documentation 关于依赖注入范围。


    第二个注意事项:您的 AddSeedData 扩展方法是 async void 而你并不等待结果。你应该返回一个任务( async Task 调用 AddSeedData().GetAwaiter().GetResult() 以确保在播种完成之前阻止。

        2
  •  -1
  •   Brad    6 年前

    这个 Configure() 方法允许参数依赖项注入,因此可以执行以下操作。

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ISeedDataService seedService)
    {
        seedService.EnsureSeedData().Wait(); // Configure() is not async so you have to wait
    }