3

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

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

我知道我可以在 Layout 模板中使用 SystemClock.Instance ......改为引用一个全局的、可测试的 IClock 会更好。

4

2 回答 2

5

您可以使用子操作

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

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>
于 2013-02-18T22:35:37.650 回答
0

如果您正在寻找可测试的DateTime.Now,则可以使用SystemTime.Now(),如Ayende Rahien 的这篇文章中所述。您可以创建一个Func<DateTime>默认为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而不是SystemTime.Now

于 2013-02-18T23:09:53.553 回答