【问题标题】:How to initialise BaseModel in BaseController如何在 BaseController 中初始化 BaseModel
【发布时间】:2015-10-09 18:11:31
【问题描述】:

我有一类属性,这些属性是从我需要在我的 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
{
}

然后我创建了一个“基本控制器”,我的所有控制器都将继承自:

public class BaseController : Controller
{
    public BaseController()
    {
    }
}

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        HomeIndexViewModel model = new HomeIndexViewModel();
        return View(model);
    }
}

这是按预期工作的,我可以在我看来调用@Model.foo 并获得foo value

但是我不认为我应该在它的构造函数中初始化 BaseModel 的值,因为这没有使用依赖注入并且将变得难以进行单元测试。

如何将值 foobar 的设置移动到 BaseController 中?

当然,我可以在HomeController 中设置值,但我宁愿从控制器中抽象出来,因为逻辑总是相同的,并且会使我的所有控制器膨胀。

【问题讨论】:

  • @nopeflow 你能举例说明你的意思吗?谢谢
  • @Curl 我已经删除了我的评论,我认为我误解了这个问题,现在我发现我的评论毫无意义。
  • 你不想把这个参数传递给BaseController构造函数吗?

标签: c# asp.net-mvc inheritance dependency-injection model


【解决方案1】:

我认为问题在于您在 action 中创建模型的实例,因此基本控制器没有引用对象来设置属性。

就我个人而言,我可能会在基本控制器中选择一些“工厂类型”功能,该功能负责根据需要创建模型。

例如这样的:

public class BaseController : Controller
{
    public T CreateBaseModel<T>() where T : BaseModel, new()
    {
        return new T
        {
            foo = "foo value",
            bar = "bar value"
        };
    }
}

然后,当您在操作中创建模型时,您可以这样做:

HomeIndexViewModel model = CreateBaseModel<HomeIndexViewModel>();

如果由于某种原因您需要将参数传递给模型构造函数,那么您可以有这样的重载:

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);

替代方案

上述方法的主要好处是您可以在操作代码中访问foobar 属性。但是,如果您不关心这一点并且只需要可以从“视图”页面中访问这些值,那么您可以覆盖 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);
}

在那里签入null意味着它只会尝试应用从BaseModel继承的模型的值,这意味着您仍然可以放心地使用其他模型。

使用这种方法,您的操作代码可以恢复到原来的样子:

HomeIndexViewModel model = new HomeIndexViewModel();
return View(model);

【讨论】:

  • OnActionExecuted 成功了!!谢谢 - 先生,一百万个赞誉
  • @Steven:感谢编辑,虽然不知道但看起来不错!
猜你喜欢
  • 1970-01-01
  • 2018-09-04
  • 2022-06-17
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 2021-03-23
  • 2019-05-17
相关资源
最近更新 更多