如何在MVC4中将IClock注入_Layout?

时间:2013-02-18 22:27:40

标签: asp.net-mvc-4 ninject nodatime

默认的MVC模板使用“@ DateTime.Now.Year”来显示版权年份,但我宁愿在任何地方使用NodaTime。

我目前正在使用Ninject将IClock实例注入到控制器中,这些控制器会执行特定时间或日期。是否有推荐的方法来访问MVC中的“全局IClock”,类似于“DateTime.Now”?我想我可以将IClock注入每个Controller,然后将其传递到每个视图中,但有时可以访问全局内容。

我知道我可以在布局模板中使用SystemClock.Instance ...相反,引用全局的,可测试的IClock会更好。

2 个答案:

答案 0 :(得分:4)

您可以使用child action

首先编写一个控制器,您可以像往常一样使用依赖注入,它将包含子操作:

public class CopyrightController: Controller
{
    private readonly IClock clock;
    public CopyrightController(IClock clock)
    {
        this.clock = clock;
    }

    [ChildActionOnly]
    public ActionResult Index()
    {
        // In this example I am directly passing the IClock instance
        // to the partial view as model but in a real application
        // you might want to use a view model here
        return PartialView(this.clock);
    }
}

然后您可以拥有相应的部分视图(~/Views/Copyright/Index.cshtml):

@model IClock
<div>Copyright ...</div>

最后在你的_Layout中调用这个子动作:

<footer>
    @Html.Action("Copyright", "Index")
</footer>

答案 1 :(得分:0)

如果您正在寻找可测试的DateTime.Now,则可以使用SystemTime.Now(),详见this post by Ayende Rahien。您可以创建默认为Func<DateTime>的{​​{1}},但可以将其设置为测试中的特定日期。它可以节省您引入另一个依赖项这是功能:

DateTime.Now

无论您在何处使用public static class SystemTime { public static Func<DateTime> Now = () => DateTime.Now; } ,都应使用DateTime.Now。你可以在你的测试中设置它:

SystemTime.Now

如果您对日期的使用有足够的测试覆盖率,则应该捕获使用SystemTime.Now = () => new DateTime(2012, 7, 1).Date; 而不是DateTime.Now的任何实例