这是一个新手问题。在ASP.NET Core 3.1 中,我很难从自己的自定义类中访问依赖项注入的服务
我可以从控制器或剃刀页面中访问服务,例如,我可以获得配置和数据上下文信息:
public class DetailModel : PageModel
{
private readonly MyDataContext _context;
private readonly IConfiguration _config;
public DetailModel(MyDataContext context, IConfiguration config)
{
_context = context;
_config = config;
}
etc......
}
我现在希望从一个自定义类的构造函数访问这些,该类不是控制器或剃刀页面。例如,我使用的是:
public class ErrorHandling
{
private readonly MyDataContext _context;
private readonly IConfiguration _config;
public ErrorHandling(MyDataContext context, IConfiguration config)
{
_context = context;
_config = config;
}
}
问题是,当我实例化我的类时,它坚持要我将服务值传递到构造函数:
var myErrorHandler = new ErrorHandling(`<wants me to pass context and config values here>`)
这违背了DI的全部观点。我想我错过了一些基本的东西!
我错过了什么?
您也可以在Startup.cs:中将ErrorHandling
注册为服务
public void ConfigureServices(IServiceCollection services)
{
// other stuff..
services.AddScoped<ErrorHandling>(); // this should work as long as both 'MyDataContext' and 'IConfiguration' are also registered
}
如果您在页面模型中需要ErrorHandling
的实例,您可以在构造函数中指定它,ASP.NET Core将在运行时为您解析它。
这样你就不必new
它:
public class DetailModel : PageModel
{
private readonly MyDataContext _context;
private readonly IConfiguration _config;
private readonly ErrorHandling _errorHandling;
public DetailModel(ErrorHandling errorHandling, MyDataContext context, IConfiguration config)
{
_context = context;
_config = config;
_errorHandling = errorHandling;
}
}
这篇文章可能很有用:ASP.NET Core 中的依赖项注入
如果您不想注册为服务,可以使用ActivatorUtilities.CreateInstance来解决ErrorHandling。
使用直接和/或从IServiceProvider提供的构造函数参数实例化类型。
例如:
// IServiceProvider serviceProvider = ...;
var errorHandling = ActivatorUtilities.CreateInstance<ErrorHandling>(serviceProvider);
但是您需要小心这个解决方案:
ServiceProvider作用域应等于依赖对象(MyDataContext,IConfiguration(。否则,您将得到一个异常,如:
var errorHandling = ActivatorUtilities.CreateInstance<ErrorHandling>(app.ApplicationServices); // An exception of type 'System.InvalidOperationException' occurred // in Microsoft.Extensions.DependencyInjection.dll but was not handled in user cod // e: 'Cannot resolve scoped service 'three.MyDataContext' from root provider.'
为此,您可以创建一个范围来解决ErrorHandling:
using (var scope = app.ApplicationServices.CreateScope()) { var errorHandling = ActivatorUtilities.CreateInstance<ErrorHandling>(scope.ServiceProvider); }
依赖项注入服务不会在IDisposable实例上调用Dispose,甚至超出范围。
为此,您应该自己调用Dispose((:
using (var scope = app.ApplicationServices.CreateScope()) { using var disposablClass = ActivatorUtilities.CreateInstance<DisposablClass>(scope.ServiceProvider); }
ActivatorUtilities。即使您使用相同的ServiceProvider:,CreateInstance也会新建一个实例
using (var scope = app.ApplicationServices.CreateScope()) { var errorHandling1 = ActivatorUtilities.CreateInstance<ErrorHandling>(scope.ServiceProvider); Console.WriteLine(errorHandling1.GetHashCode()); // 11903911 var errorHandling2 = ActivatorUtilities.CreateInstance<ErrorHandling>(scope.ServiceProvider); Console.WriteLine(errorHandling2.GetHashCode()); // 40026340 }