7

我在 ASP.Net MVC 应用程序中使用 Ninject 进行依赖注入(这是我第一个使用 Ninject 或 DI 的项目)。

我选择使用 Model-View-ViewModel 模式。视图模型将提供我将绑定到实际视图的所有属性,但还需要访问数据库以获取数据列表等内容。例如:

public class CreateGetIncidentViewModel
{

    private IDBContext _dbContext = null;

    [Required]
    public EmployeeType EmployeeType { get; set; }


    [Required]
    [StringLength(50)]
    public string Department { get; set; }

    /
    public IEnumerable<SelectListItem> GetEmployeeTypeSelectList()
    {
        // Simplified for brevity
        var employeeTypes = _dbContext.EmployeTypes.Where().... // Go select the employee types

        var employeeTypeSelectList = new List<SelectListItem>();

        foreach(var employeeType in employeeTypes){
            employeeTypeSelectList.Add(new SelectListItem(){
                // Set select list properties
            });
        }           

        return employeeTypeSelectList;
    }
}

我的问题是:

  • IDBContext 是 Ninject 中的一个注册依赖项。通过实例化直接访问具体类型是不行的。
  • 我必须以某种方式将该依赖项注入到此类中,或者以某种方式通过其他已经解决了依赖项的类来访问该依赖项。

鉴于我的 ViewModel 经常通过模型绑定由 ASP.Net MVC 自动补充,我如何将我的依赖项添加到我的 ViewModel 中?

我经历了多种方式,但它们看起来都很脏。我可以(但不想)

  • 实现服务定位器模式只是简单地从 ViewModel 中解决我的 IDBContext 依赖关系。
  • 在我的控制器中解析 IDBContext 并在手动构建 ViewMode 时将其传递到我的 ViewModel 中,即new CreateGetIncidentViewModel(dbContext);
    • 这并不能解决视图模型被 MVC 水合的问题,尽管当模型被发布到一个动作时

建议?

4

2 回答 2

13

Given that my ViewModel is often hydrated by ASP.Net MVC automatically through model binding, how do I get my dependency into my ViewModel?

You could write a custom model binder that will inject the dependency into the view model constructor.

This being said, using the MVVM pattern in ASP.NET MVC IMHO is wrong approach from the beginning and if you go that way you must be prepared for lots of suffering. Are you ready for that?

If not, here's what I would recommend you:

Controller -> Domain model -> View model -> View

In this pattern you have the controller knowing about the repository (DbContext - being injected automatically into it by your DI framework).

Flow 1:

  1. The controller receives a request from the user
  2. The controller uses the repository to query one or more domain models
  3. The controller uses a mapping layer to map those domain models to a view model
  4. The controller passes this (single) view model to the view for rendering

Flow 2:

  1. The controller receives a request from the view (form submit for example)
  2. The model binder automatically binds the request body to a single view model that your controller action is taking as argument
  3. The controller is using a mapping layer to map this view model to one or more domain models
  4. The controller is using the repository to update those domain models.

In this examples the view model doesn't know anything about any repository or data access or DbContexts. The view model is the representation of the view. The mapping between the domain model and the view is a responsibility of the controller (which could be delegated to a mapping layer). Personally I use AutoMapper to perform the mapping between my domain models and view models.

于 2013-05-21T20:58:57.937 回答
2

如果您希望使用 Darin 提到的自定义模型绑定器路线,请查看:https ://stackoverflow.com/a/24166483/71906

于 2014-06-11T16:10:14.093 回答