2

在我的 MVC 4 项目中,我有一个像这样的模型:

public class MyModel
{
    private readonly IService MyService;

    public MyModel([Dependency]IService service)
    {
        this.MyService = service;
    }
    // ...
}

我的控制器有一个动作,它是一个 HttpPost,如:

[HttpPost]
public ActionResult Show(MyModel myModel)
{
    // do stuff

我的控制器没有(也不应该)有我的 IoC 容器的实例。当 HttpPost 发生并调用操作时,MVC 在执行模型绑定时尝试创建我的模型的实例。它需要一个无参数的构造函数来做到这一点。如果它使用默认构造函数创建模型,则不会设置 MyService,并且模型不会存在所有依赖项。我不想调用 myModel.Init(someIServiceInstance)。我想插入框架,以便在创建模型时解决依赖关系(调用正确的构造函数)。

我目前使用 Unity 作为我的依赖解析器,并且有一些工厂用于控制器、服务客户端等。对于控制器,我能够注册 ControllerFactory 并将依赖项传递给控制器​​,但我没有看到我可以注册的 ModelFactory。我不太关心绑定过程本身。模型实例化后,我对绑定的完成方式感到满意。我只想实现模型的创建/构造方式。如果 ModelFactory 使用对容器的引用来解决依赖关系,我也可以(我可以将容器作为构造函数的参数注入工厂,我只是不希望控制器直接引用容器)。

有没有人有一个 ModelFactory(或 ModelBinder,和/或 ModelBinderResolver 等)的样本来处理模型的创建,然后依靠框架实现来完成其余的绑定过程?

4

2 回答 2

4

您可以编写自定义模型绑定器:

public class MyModelModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        // TODO: create the model instance here using your DI framework or the 
        // DependencyResolver which is more correct
    }
}

然后在你的注册这个模型活页夹Global.asax

ModelBinders.Binders.Add(typeof(MyModel), new MyModelModelBinder());

但通常这是不好的做法。我建议您使用视图模型并让您的控制器操作将视图模型作为参数并将视图模型传递给视图。这些视图模型将具有无参数构造函数。然后你可以将你的域模型或存储库注入到控制器构造函数中。

于 2012-10-18T16:06:07.010 回答
2

我想我想通了:

public class MyModelBinder : DefaultModelBinder
{
    private readonly UnityContainer container;

    public MyModelBinder(UnityContainer container)
    {
        this.container = container;
    }

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        if (modelType == null)
        {
            return base.CreateModel(controllerContext, bindingContext, null);
        }

        return this.container.Resolve(modelType);
    }
}

在 Global.asax、Application_Start() 或您的 IoC 配置中:

ModelBinders.Binders.Add(typeof(object), new MyModelBinder(container));
于 2012-10-18T17:19:25.000 回答