Cur*_*urt 3 c# asp.net-mvc inheritance dependency-injection model
我有一类属性,这些属性是从我在MVC应用程序的每个视图中都需要的服务设置的.
因此,我创建了一个"基本视图模型",我的视图模型将从中继承.
public class BaseModel
{
public BaseModel()
{
foo = "foo value";
bar = "bar value";
}
public string foo { get; set; }
public string bar { get; set; }
}
public class HomeIndexViewModel : BaseModel
{
}
Run Code Online (Sandbox Code Playgroud)
然后我创建了一个"基本控制器",我的所有控制器将继承自:
public class BaseController : Controller
{
public BaseController()
{
}
}
public class HomeController : BaseController
{
public ActionResult Index()
{
HomeIndexViewModel model = new HomeIndexViewModel();
return View(model);
}
}
Run Code Online (Sandbox Code Playgroud)
这是按预期工作的,我可以@Model.foo
在我的视图中调用并获取foo value
.
但是我不相信我应该初始化BaseModel
它的构造函数的值,因为这不使用依赖注入并且将变得难以进行单元测试.
我怎样才能移动值的设置foo
,并bar
进入BaseController
?
当然我可以在其中设置值HomeController
,但我宁愿从控制器中抽象出来,因为逻辑总是相同的并且会使我的所有控制器膨胀.
我认为问题是,你正在创建模型内的情况下采取行动,因此基本控制器没有参考对象设置的属性.
就个人而言,我可能会在基本控制器中选择一些"工厂类型"功能,负责根据需要创建模型.
像这样的东西例如:
public class BaseController : Controller
{
public T CreateBaseModel<T>() where T : BaseModel, new()
{
return new T
{
foo = "foo value",
bar = "bar value"
};
}
}
Run Code Online (Sandbox Code Playgroud)
然后,当您在操作中创建模型时,您可以这样做:
HomeIndexViewModel model = CreateBaseModel<HomeIndexViewModel>();
Run Code Online (Sandbox Code Playgroud)
如果由于某种原因你需要将参数传递给模型构造函数,那么你可以像这样重载:
public T CreateBaseModel<T>(params object[] args) where T : BaseModel
{
T model = (T)Activator.CreateInstance(typeof(T), args);
model.foo = "foo";
return model;
}
HomeIndexViewModel model = CreateBaseModel<HomeIndexViewModel>(param1, param2, etc);
Run Code Online (Sandbox Code Playgroud)
替代
上述方法的主要好处是您可以访问操作代码中的foo
和bar
属性.但是,如果您不关心这一点并且只需要在"视图"页面中可以访问这些值,那么您可以覆盖该OnActionExecuted
方法并在其中应用这些值.这种方法的好处是您不需要改变在动作中创建模型的方式......
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
BaseModel model = filterContext.Controller.ViewData.Model as BaseModel;
if (model != null)
{
model.foo = "foo value";
model.bar = "bar value";
}
base.OnActionExecuted(filterContext);
}
Run Code Online (Sandbox Code Playgroud)
进行null
检查意味着它只会尝试应用继承的模型的值BaseModel
,这意味着您仍然可以毫无顾虑地使用其他模型.
使用这种方法,您的操作代码可以追溯到最初的方式:
HomeIndexViewModel model = new HomeIndexViewModel();
return View(model);
Run Code Online (Sandbox Code Playgroud)