如何在模型(或虚拟机)中使用 DI?
Posted
技术标签:
【中文标题】如何在模型(或虚拟机)中使用 DI?【英文标题】:How to use DI in Model (or VM)? 【发布时间】:2022-01-10 00:24:09 【问题描述】:我曾尝试分离 DAL 并将其注入 Program.cs 中的 DI,如下所示
services.AddScoped<IDataLoadServices, DataLoadServices>();
然后要从 DB 中获取数据并将其放入 Model(也许可以称之为 ViewModel)我需要从 Model 类的构造函数中获取这些服务,如下所示
class MyModel
public IList Countriesget;set;
public int SelectedCountryCodeget;set;
//default Ctor
//call When creating by Model Binding
public MyModel()
//call when creating by Factory
[ActivatorUtilitiesConstructor]
public MyModel(IDataLoadServices ser)
Countries = ser.LoadMyListFromDB();
在 Controller Action 中,我可以使用 FactoryServices 创建 MyModel 实例。(此处未显示) 之后成功传递给 View。
@model MyModel
<form method="post" asp-controller="MyController">
...
<select asp-for="SelectedCountryCode" asp-items="@(new SelectList(Model.Countries, "CountryCode", "CountryName"))">
</select>
<input type="hidden" asp-for="SelectedCountryCode" />
...
在提交后的控制器操作中
[HttpsPost]
public IActionResult Submited(MyModel model)
//model.Countries == null
//model.SelectedCountryCode == 0 ????
我认为 MyModel 的问题是在具有默认构造函数的模型绑定阶段创建的,因此它无法获取国家列表并且无法解析 SelectedCountryCode。
-
是这样吗?
有什么办法绕过这个问题吗?
【问题讨论】:
【参考方案1】:您的视图显示的大部分数据应该从控制器传入。我会尽可能保持模型裸露。相反,将IDataLoadServices
注入控制器。
public class WorldController : Controller
private readonly IDataLoadServices _service;
public WorldController(IDataLoadServices service)
_service = service
查看有关此的文档。 Dependency injection into controllers in ASP.NET Core
【讨论】:
【参考方案2】:对吗? --> 可能是,但您可以从模型中删除该默认 ctor。因为它会默认创建。
有绕过这个问题的想法吗? --> 有很多方法可以做到这一点。
【讨论】:
没有默认 ctor,因为模型绑定无法解析 IDataLoadServices,所以您会合规。并且将 IDataServices 放入 Controller 将与 Get Action(将模式放入 View)一起使用,但不适用于 Post Action(从模型绑定中获取模型) 您是否尝试过我上面提到的选项模式。 ?您是如何注册服务的? 我正在阅读选项模式但还没有理解。我在 Progarm.cs 的 ConfigureServices 方法中注册了 IDataLoadServices,例如“services.AddTransient没错 --> ModelBininding 创建新的 MyModel 使用 Default Tor
这不应该成为问题。我在 Control Action 中收到的 MyModel 实例应该有 SelectedCountryCode != 0。=> 我在 Mapping 类中失败了。
[HttpsPost]
public IActionResult Submited(MyModel model)
//model.Countries == null => ok. because cant resolve IDataLoadServices
//model.SelectedCountryCode != 0
万一 someOne 需要 ModelBining 调用参数 Tor:
创建工厂以将 DI 注入 Model Tor。
public class FactoryServices : IFactoryServices
private readonly IServiceProvider _sp;
public FactoryServices(IServiceProvider serviceProvider)
_sp = serviceProvider;
public T Create<T>(params object[] p)
return ActivatorUtilities.CreateInstance<T>(_sp, p);
创建自定义活页夹
创建自定义 BinderProvider
注册 DI
For 1., 3., 4. refer to this answer
【讨论】:
以上是关于如何在模型(或虚拟机)中使用 DI?的主要内容,如果未能解决你的问题,请参考以下文章