在 ASP.NET Core 中,您如何在非控制器 class 中获得作用域服务实例?
In ASP.NET Core how do you get a scoped service instance in a non-controller class?
在 ASP.NET Core 3.1 网站中,我试图在 class 中使用构造函数依赖注入,它不是控制器,它似乎没有按预期工作。 MyService.cs 似乎没有得到 class 实例并抛出一个错误......这需要我从控制器传递它而不是仅仅做依赖按预期在构造函数中注入。
需要澄清的一些注意事项:MyService.cs 是业务规则的集合,而不是我要注入的服务(也称为业务服务)。我想要做的就是访问在 Startup.cs 中声明的 DataAccessLayerInterface DataAccessLayerService 实例。问题是当我尝试在构造函数中使用依赖注入时它不起作用并抛出编译错误。如果我在控制器中做同样的事情,尽管它能正常工作,但我很困惑。
最终我打算将其构建为数据层,但现在我只是传递一个字符串,目的是稍后构建它。以下是我一直在研究的相关部分。为简洁起见,我删除了命名空间和 using 语句引用。我在适用的地方使用 Microsoft.Extensions.DependencyInjection。
Startup.cs
public void ConfigureServices(IServiceCollection services) {
services.AddScoped<DataAccessLayerInterface> (options => new DataAccessLayerService("acorns"));
}
MyAPIController.cs
public class MyAPIController : Controller {
public ActionResult tell_me() {
MyService _business_service = new MyService();
string _response = _business_service.tell_me_something();
Hashtable _data = new Hashtable();
_data.Add("squirrels eat", _response);
return Json(_data);
}
}
MyService.cs
public class MyService {
DataAccessLayerInterface _DataAccessLayerService;
public MyService(DataAccessLayerInterface MyDataAccessLayerService) {
this._DataAccessLayerService = MyDataAccessLayerService;
}
public string tell_me_something() {
return _DataAccessLayerService.we_eat();
}
}
DataAccessLayerHelper.cs
public interface DataAccessLayerInterface {
string we_eat();
}
public class DataAccessLayerService : DataAccessLayerInterface {
private string _food = "rocks";
public string we_eat() {
return this._food;
}
public DataAccessLayerService(string MyFood) {
this._food = MyFood;
}
}
如果我在控制器中添加构造函数依赖注入,然后将它传递给每个部分,它在技术上是可行的,但在架构上似乎是不正确的,因为业务服务不需要任何参数并且应该完全独立于控制器。即:
private DataAccessLayerInterface _DataAccessLayerService;
public UserAPIController(DataAccessLayerInterface MyDataAccessLayerService) {
this._DataAccessLayerService = MyDataAccessLayerService;
}
// in tell_me() action result, now I have to pass the object like so
string _response = _business_service.tell_me_something(_DataAccessLayerService);
我没有在 MyService.cs 中注入构造函数,而是尝试像这样在构造函数中获取实例,但它似乎也不起作用...
public MyService() {
this._DataAccessLayerService = (DataAccessLayerInterface)ServiceProvider.GetService(typeof(DataAccessLayerInterface));
}
在我看来,实例是通过依赖注入创建的,但它似乎只适用于控制器,而不适用于我自己的自定义 classes。有什么建议吗?
有 3 种方法可以解决您的问题。
1- 好办法
像这样为您的服务创建一个界面
public interface IMyService
{
string tell_me_something();
}
public class MyService : IMyService
{
DataAccessLayerInterface _DataAccessLayerService;
public MyService(DataAccessLayerInterface MyDataAccessLayerService)
{
this._DataAccessLayerService = MyDataAccessLayerService;
}
public string tell_me_something()
{
return _DataAccessLayerService.we_eat();
}
}
并将其添加到 DI
services.AddScoped<IMyService, MyService> ();
并注入 IMyService
到控制器。
2- 将 MyService 注入 DI
services.AddScoped(provider=>
new MyService(provider.GetRequiredService<DataAccessLayerInterface>());
并将MyService
注入控制器;
3- 方法不对
创建服务实例时使用:
var service = new MyService(HttpContext.RequestServices.GetRequiredService<DataAccessLayerInterface>());
在 ASP.NET Core 3.1 网站中,我试图在 class 中使用构造函数依赖注入,它不是控制器,它似乎没有按预期工作。 MyService.cs 似乎没有得到 class 实例并抛出一个错误......这需要我从控制器传递它而不是仅仅做依赖按预期在构造函数中注入。
需要澄清的一些注意事项:MyService.cs 是业务规则的集合,而不是我要注入的服务(也称为业务服务)。我想要做的就是访问在 Startup.cs 中声明的 DataAccessLayerInterface DataAccessLayerService 实例。问题是当我尝试在构造函数中使用依赖注入时它不起作用并抛出编译错误。如果我在控制器中做同样的事情,尽管它能正常工作,但我很困惑。
最终我打算将其构建为数据层,但现在我只是传递一个字符串,目的是稍后构建它。以下是我一直在研究的相关部分。为简洁起见,我删除了命名空间和 using 语句引用。我在适用的地方使用 Microsoft.Extensions.DependencyInjection。
Startup.cs
public void ConfigureServices(IServiceCollection services) {
services.AddScoped<DataAccessLayerInterface> (options => new DataAccessLayerService("acorns"));
}
MyAPIController.cs
public class MyAPIController : Controller {
public ActionResult tell_me() {
MyService _business_service = new MyService();
string _response = _business_service.tell_me_something();
Hashtable _data = new Hashtable();
_data.Add("squirrels eat", _response);
return Json(_data);
}
}
MyService.cs
public class MyService {
DataAccessLayerInterface _DataAccessLayerService;
public MyService(DataAccessLayerInterface MyDataAccessLayerService) {
this._DataAccessLayerService = MyDataAccessLayerService;
}
public string tell_me_something() {
return _DataAccessLayerService.we_eat();
}
}
DataAccessLayerHelper.cs
public interface DataAccessLayerInterface {
string we_eat();
}
public class DataAccessLayerService : DataAccessLayerInterface {
private string _food = "rocks";
public string we_eat() {
return this._food;
}
public DataAccessLayerService(string MyFood) {
this._food = MyFood;
}
}
如果我在控制器中添加构造函数依赖注入,然后将它传递给每个部分,它在技术上是可行的,但在架构上似乎是不正确的,因为业务服务不需要任何参数并且应该完全独立于控制器。即:
private DataAccessLayerInterface _DataAccessLayerService;
public UserAPIController(DataAccessLayerInterface MyDataAccessLayerService) {
this._DataAccessLayerService = MyDataAccessLayerService;
}
// in tell_me() action result, now I have to pass the object like so
string _response = _business_service.tell_me_something(_DataAccessLayerService);
我没有在 MyService.cs 中注入构造函数,而是尝试像这样在构造函数中获取实例,但它似乎也不起作用...
public MyService() {
this._DataAccessLayerService = (DataAccessLayerInterface)ServiceProvider.GetService(typeof(DataAccessLayerInterface));
}
在我看来,实例是通过依赖注入创建的,但它似乎只适用于控制器,而不适用于我自己的自定义 classes。有什么建议吗?
有 3 种方法可以解决您的问题。
1- 好办法
像这样为您的服务创建一个界面
public interface IMyService
{
string tell_me_something();
}
public class MyService : IMyService
{
DataAccessLayerInterface _DataAccessLayerService;
public MyService(DataAccessLayerInterface MyDataAccessLayerService)
{
this._DataAccessLayerService = MyDataAccessLayerService;
}
public string tell_me_something()
{
return _DataAccessLayerService.we_eat();
}
}
并将其添加到 DI
services.AddScoped<IMyService, MyService> ();
并注入 IMyService
到控制器。
2- 将 MyService 注入 DI
services.AddScoped(provider=>
new MyService(provider.GetRequiredService<DataAccessLayerInterface>());
并将MyService
注入控制器;
3- 方法不对
创建服务实例时使用:
var service = new MyService(HttpContext.RequestServices.GetRequiredService<DataAccessLayerInterface>());