在我的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在进行模型绑定时尝试创建模型的实例。它需要一个无参数构造函数来完成。如果它使用默认构造函数创建Model,则不会设置MyService,并且Model不会存在所有依赖项。我不想调用myModel.Init(someIServiceInstance)。我想插入框架,以便在创建模型时解析依赖关系(调用正确的构造函数)。
我目前正在使用Unity作为我的依赖解析器,并且有一些工厂用于控制器,服务客户端等。对于控制器,我能够注册ControllerFactory并将依赖项传递给控制器,但我不知道看到我可以注册的ModelFactory。我并不关心绑定过程本身;一旦模型被实例化,我对如何完成绑定感到满意。我只想实现如何创建/构建模型。我也没关系,如果ModelFactory使用对容器的引用来解决依赖关系(我可以将容器注入工厂作为它的构造函数的参数,我只是不希望控制器直接引用容器)。
是否有人拥有ModelFactory(或ModelBinder和/或ModelBinderResolver等)的样本,它们将处理模型的创建,然后依靠框架实现来完成剩余的Binding过程?
答案 0 :(得分: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());
但通常这是不好的做法。我建议您使用视图模型并让控制器操作将视图模型作为参数并将视图模型传递给视图。那些视图模型将具有无参数构造函数。然后,您可以将域模型或存储库注入控制器构造函数。
答案 1 :(得分: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));