尝试为绑定对象添加依赖注入
Trying to add dependency injection for binding object
我正在开发基于 .NET Core 2.0 的 Web 应用程序。
我有 class ReportModel
,用于在控制器方法中绑定参数。而且我在同一个 class 中也有一些功能(方法 Get()
开始做一些事情,基于提供的绑定参数),例如:
[HttpGet]
public JsonResult GetReport(ReportModel model)
{
return new JsonResult( new { model.Get().ToString() });
}
现在我要 .NET 5
并想通过 DI 添加 IConfiguration
到 ReportModel
.
我希望它按以下方式工作:为 ReportModel
添加构造函数,为 DI 添加构造函数 IConfiguration
以提供配置:
public class ReportModel
{
private readonly IConfiguration _configuration;
public ReportModel(IConfiguration configuration)
{
_configuration = configuration;
}
...
但是当我尝试 运行 GetReport(ReportModel model)
方法时 returns 异常:
InvalidOperationException: Could not create an instance of type 'ViewData.Models.Data.ReportModel'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Record types must have a single primary constructor. Alternatively, give the 'data' parameter a non-null default value.
一点解释:还有几个 classes,我用这种方式(将参数绑定到属性并将功能存储在同一个 class 中),所以我真的不想为 IConfiguration
.
添加每个方法 Get()
附加参数
我应该如何正确执行此操作?我错过了什么吗?或者它只是行不通?
如果我使用的术语有误,我深表歉意,如果您指出错误的内容,我们将很高兴。谢谢。
这是一个很好的问题。你走在正确的轨道上。
在我看来,ReportModel
根本不应该使用依赖注入。该模型应该只是一个 属性 对传入参数建模的包。
在控制器操作中执行逻辑(或以其他方式处理)。
How am I supposed to do this properly? Am I missing something? Or It's just don't work this way?
这样不行。
首先,模型不应该注入依赖项,它们只是 class 用于从请求中获取输入。
不过,这也是错误的: ... GetReport(ReportModel model)
。这依赖于 ASP.NET Core 默认注入一个新的 ReportModel 这一事实——如果这种行为发生变化,您的代码会神奇地停止工作。
您的代码应该如下所示:
public class ReportsController
{
private readonly IReportModelService _reportModelService;
public ReportsController(IReportModelService reportModelService)
{
_reportModelService = reportModelService;
}
[HttpGet]
public IActionResult GetReport()
{
return new JsonResult(_reportModelService.GetReport());
}
}
连同构建报告的适当 class,例如:
public class ReportModelService: IReportModelService
{
private readonly IConfiguration _configuration;
public ReportModelService(IConfiguration configuration)
{
_configuration = configuration;
}
public string GetReport()
{
// your logic here
}
}
net core 中使用的默认 DI 容器只能在构造函数内部注入依赖项,在这种情况下是控制器构造函数,而不是在 action 内部,因为 action 没有构造函数。所以像这样更改你的代码
public class ReportController
{
private readonly ReportModel _model
public ReportController(ReportModel model )
{
_model=model;
}
[HttpGet]
public JsonResult GetReport()
{
return new JsonResult( new { _model.Get().ToString() });
}
}
并且不要忘记将 DI 添加到启动中
services.AddScoped<ReportModel>();
所以我听从了@Camilo 的建议。我的计划是将 ReportModel
拆分为 ReportParams
(DTO class)和 ReportProvider
(业务逻辑 class)。然后,为 ReportProvider
添加构造函数,以便通过调用 ActivatorUtilities.CreateInstance<ReportProvider>()
通过 依赖注入 提供 IConfiguration
模型拆分:
public class ReportParams
{
public double Size { get; set; }
// other properties.
}
public class ReportProvider
{
private readonly IConfiguration _configuration;
public ReportProvider(IConfiguration configuration)
{
_configuration = configuration;
}
public List<string> Get(ReportParams args)
{
// ...
}
}
报表控制器:
public class ReportController: Controller
{
private readonly IServiceProvider _services;
public ReportController(IServiceProvider services)
{
_services = services;
}
public IActionResult Get(ReportParams args)
{
ReportProvider model = ActivatorUtilities.CreateInstance<ReportProvider>(_services);
return JsonResult(model.Get(args));
}
}
我正在开发基于 .NET Core 2.0 的 Web 应用程序。
我有 class ReportModel
,用于在控制器方法中绑定参数。而且我在同一个 class 中也有一些功能(方法 Get()
开始做一些事情,基于提供的绑定参数),例如:
[HttpGet]
public JsonResult GetReport(ReportModel model)
{
return new JsonResult( new { model.Get().ToString() });
}
现在我要 .NET 5
并想通过 DI 添加 IConfiguration
到 ReportModel
.
我希望它按以下方式工作:为 ReportModel
添加构造函数,为 DI 添加构造函数 IConfiguration
以提供配置:
public class ReportModel
{
private readonly IConfiguration _configuration;
public ReportModel(IConfiguration configuration)
{
_configuration = configuration;
}
...
但是当我尝试 运行 GetReport(ReportModel model)
方法时 returns 异常:
InvalidOperationException: Could not create an instance of type 'ViewData.Models.Data.ReportModel'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Record types must have a single primary constructor. Alternatively, give the 'data' parameter a non-null default value.
一点解释:还有几个 classes,我用这种方式(将参数绑定到属性并将功能存储在同一个 class 中),所以我真的不想为 IConfiguration
.
Get()
附加参数
我应该如何正确执行此操作?我错过了什么吗?或者它只是行不通?
如果我使用的术语有误,我深表歉意,如果您指出错误的内容,我们将很高兴。谢谢。
这是一个很好的问题。你走在正确的轨道上。
在我看来,ReportModel
根本不应该使用依赖注入。该模型应该只是一个 属性 对传入参数建模的包。
在控制器操作中执行逻辑(或以其他方式处理)。
How am I supposed to do this properly? Am I missing something? Or It's just don't work this way?
这样不行。
首先,模型不应该注入依赖项,它们只是 class 用于从请求中获取输入。
不过,这也是错误的: ... GetReport(ReportModel model)
。这依赖于 ASP.NET Core 默认注入一个新的 ReportModel 这一事实——如果这种行为发生变化,您的代码会神奇地停止工作。
您的代码应该如下所示:
public class ReportsController
{
private readonly IReportModelService _reportModelService;
public ReportsController(IReportModelService reportModelService)
{
_reportModelService = reportModelService;
}
[HttpGet]
public IActionResult GetReport()
{
return new JsonResult(_reportModelService.GetReport());
}
}
连同构建报告的适当 class,例如:
public class ReportModelService: IReportModelService
{
private readonly IConfiguration _configuration;
public ReportModelService(IConfiguration configuration)
{
_configuration = configuration;
}
public string GetReport()
{
// your logic here
}
}
net core 中使用的默认 DI 容器只能在构造函数内部注入依赖项,在这种情况下是控制器构造函数,而不是在 action 内部,因为 action 没有构造函数。所以像这样更改你的代码
public class ReportController
{
private readonly ReportModel _model
public ReportController(ReportModel model )
{
_model=model;
}
[HttpGet]
public JsonResult GetReport()
{
return new JsonResult( new { _model.Get().ToString() });
}
}
并且不要忘记将 DI 添加到启动中
services.AddScoped<ReportModel>();
所以我听从了@Camilo 的建议。我的计划是将 ReportModel
拆分为 ReportParams
(DTO class)和 ReportProvider
(业务逻辑 class)。然后,为 ReportProvider
添加构造函数,以便通过调用 ActivatorUtilities.CreateInstance<ReportProvider>()
IConfiguration
模型拆分:
public class ReportParams
{
public double Size { get; set; }
// other properties.
}
public class ReportProvider
{
private readonly IConfiguration _configuration;
public ReportProvider(IConfiguration configuration)
{
_configuration = configuration;
}
public List<string> Get(ReportParams args)
{
// ...
}
}
报表控制器:
public class ReportController: Controller
{
private readonly IServiceProvider _services;
public ReportController(IServiceProvider services)
{
_services = services;
}
public IActionResult Get(ReportParams args)
{
ReportProvider model = ActivatorUtilities.CreateInstance<ReportProvider>(_services);
return JsonResult(model.Get(args));
}
}