C# ASP.NET Core 2中的依赖项注入引发异常
当我尝试在C# ASP.NET Core 2中的依赖项注入引发异常,c#,asp.net-core,dependency-injection,.net-core,asp.net-core-2.0,C#,Asp.net Core,Dependency Injection,.net Core,Asp.net Core 2.0,当我尝试在Startup.cs文件的Configure方法中使用自定义DbContext时,我收到以下异常。我在版本2.0.0-preview1-005977中使用ASP.NET核心 未处理的异常:系统。异常:无法为“Communicator.Backend.Data.CommunicatorContext”类型的“Communicator.Backend.Data.CommunicatorContext”解析类型为“Communicator.Backend.Startup”的方法“Config
Startup.cs
文件的Configure
方法中使用自定义DbContext时,我收到以下异常。我在版本2.0.0-preview1-005977中使用ASP.NET核心
未处理的异常:系统。异常:无法为“Communicator.Backend.Data.CommunicatorContext”类型的“Communicator.Backend.Data.CommunicatorContext”解析类型为“Communicator.Backend.Startup”的方法“Configure”的参数“dbContext”的服务。-->System.InvalidOperationException:无法从根提供程序解析作用域服务“Communicator.Backend.Data.CommunicatorContext”
当我尝试接收其他实例时,也会抛出此异常
未处理的异常:系统。异常:无法解析“Communicator.Backend.Services.ILdapService”类型的服务。…
以下是我的ConfigureServices
和Configure
方法
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddCookieAuthentication();
services.Configure<LdapConfig>(Configuration.GetSection("Ldap"));
services.AddScoped<ILdapService, LdapService>();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, CommunicatorContext dbContext, ILdapService ldapService)
{
app.UseAuthentication();
app.UseWebSockets();
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(context, webSocket);
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
app.UseMvc();
DbInitializer.Initialize(dbContext, ldapService);
}
public void配置服务(IServiceCollection服务)
{
services.AddDbContext(options=>options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”));
services.AddCookieAuthentication();
services.Configure(Configuration.GetSection(“Ldap”));
services.addScope();
services.AddMvc();
}
public void Configure(IApplicationBuilder应用程序、IHostingEnvironment环境、ILoggerFactory loggerFactory、CommunicationorContext dbContext、ILdapService ldapService)
{
app.UseAuthentication();
app.UseWebSockets();
应用程序使用(异步(上下文,下一步)=>
{
if(context.Request.Path==“/ws”)
{
if(context.WebSockets.IsWebSocketRequest)
{
WebSocket WebSocket=等待上下文.WebSocket.AcceptWebSocketAsync();
等待回声(上下文、webSocket);
}
其他的
{
context.Response.StatusCode=400;
}
}
其他的
{
等待下一个();
}
});
app.UseMvc();
初始化(dbContext,ldapService);
}
引用文档
ASP.NET核心依赖项注入在
应用程序的启动。您可以通过以下方式请求这些服务:
在启动
类的
构造函数或其配置
或配置服务
方法之一
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddCookieAuthentication();
services.Configure<LdapConfig>(Configuration.GetSection("Ldap"));
services.AddScoped<ILdapService, LdapService>();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, CommunicatorContext dbContext, ILdapService ldapService)
{
app.UseAuthentication();
app.UseWebSockets();
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(context, webSocket);
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
app.UseMvc();
DbInitializer.Initialize(dbContext, ldapService);
}
按照以下顺序查看启动
类中的每个方法
他们被称为,可能需要以下服务:
参数:
- 在构造函数中:
,IHostingEnvironment
ILoggerFactory
- 在
方法中:ConfigureServices
IServiceCollection
- 在
方法中:Configure
,iaapplicationbuilder
,IHostingEnvironment
,iLogger工厂
IApplicationLifetime
...CommunicatorContext dbContext, ILdapService ldapService) {
这会给你带来错误。如果需要访问实现,则需要执行以下操作之一:
ConfigureServices
方法,并从服务集合访问它们。i、 e
public IServiceProvider ConfigureServices(IServiceCollection services) {
services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddCookieAuthentication();
services.Configure<LdapConfig>(Configuration.GetSection("Ldap"));
services.AddScoped<ILdapService, LdapService>();
services.AddMvc();
// Build the intermediate service provider
var serviceProvider = services.BuildServiceProvider();
//resolve implementations
var dbContext = serviceProvider.GetService<CommunicatorContext>();
var ldapService = serviceProvider.GetService<ILdapService>();
DbInitializer.Initialize(dbContext, ldapService);
//return the provider
return serviceProvider();
}
来自NKosi的解决方案之所以有效,是因为在没有参数的情况下调用
services.BuildServiceProvider()
您自己不会传递validateScopes
。由于此验证已禁用,因此不会引发异常。这并不意味着问题不存在
EF CoreDbContext
已注册到范围限定的生活方式。在ASP原生DI中,容器作用域连接到IServiceProvider
的实例。通常,当您从控制器使用DbContext
时,没有问题,因为ASP为每个请求创建一个新的作用域(IServiceProvider的新实例),然后使用它来解决此请求中的所有问题。但是,在应用程序启动期间,您没有请求范围。您有一个IServiceProvider
的实例,它没有作用域(或者换句话说,在根作用域中)。这意味着您应该自己创建一个范围。您可以这样做:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<CommunicatorContext>();
var ldapService = scope.ServiceProvider.GetRequiredService<ILdapService>();
// rest of your code
}
// rest of Configure setup
}
public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂)
{
var scopeFactory=app.ApplicationServices.GetRequiredService();
使用(var scope=scopeFactory.CreateScope())
{
var db=scope.ServiceProvider.GetRequiredService();
var ldapService=scope.ServiceProvider.GetRequiredService();
//代码的其余部分
}
//配置设置的其余部分
}
ConfigureServices
方法可以保持不变
编辑
您的解决方案将在2.0.0 RTM中工作,无需任何更改,因为将为Configure方法创建RTM范围内的服务提供程序
在Program.cs的.UseStartup()
为我工作
或者,您可以在
配置方法中创建服务范围:
var scopeFactory = ApplicationServices.GetService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
var dbContext = scope.ServiceProvider.GetService<CommunicatorDbContext>();
DbInitializer.Initializer(dbContext, ldapService);
}
var scopeFactory=ApplicationServices.GetService();
使用(var scope=scopeFactory.CreateScope())
{
var dbContext=scope.ServiceProvider.GetService();
初始化器(dbContext,ldapService);
}
虽然,正如在Slack中提到的,不要这样做;-) 在ASP.NET Core 2.0及更新版本中,您只需将所需的作用域服务注入配置
构造函数,就像您最初尝试的那样:
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
CommunicatorContext dbContext,
ILdapService ldapService)
{
// ...
}
由于中的改进,这要容易得多。谢谢,这解决了我的问题。如果我可以添加更多,在测试了这两个选项之后,我发现我仍然需要修改ConfigureServices
,从返回void
(默认情况下)到返回IServiceProvider
,以便第二个选项工作。有类似的问题。制作ConfigureServices()
返回
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
CommunicatorContext dbContext,
ILdapService ldapService)
{
// ...
}