ASP.NET MVC ViewHelpers和依赖注入

时间:2015-03-27 09:23:03

标签: asp.net-mvc dependency-injection ninject view-helpers onion-architecture

我想创建一个ViewHelper来本地化我的ASP.NET MVC应用程序。像这样:

public class Translator
{
    private readonly ITranslationRepository _repo;
    public Translator(ITranslationRepository repo)
    {
        _repo = repo;
    }

    public static string Translate(TranslationEnum translationEnum)
    {
        return _repo.GetTranslation(translationEnum, Session.LanguageId);
    }
}

(Razor)视图中的用法如下所示:

<p>@Translator.Translate(TranslationEnum.WelcomeMessage)</p>

现在问题是,我无法使Translate方法成为静态,因为我需要访问实例变量_repo

如何将存储库注入ViewHelper中,以便在上面的视图中使用它?

2 个答案:

答案 0 :(得分:3)

视图的职责只是将从控制器返回的数据转换为HTML结构。自动测试很难(不可能),所以最好是让它们尽可能地保持愚蠢。

不要在视图中使用Translator,而是将其注入控制器并让控制器调用Translator。这解决了一系列问题:

  • 让视图变得简单。
  • 提高可维护性。
  • 它提高了可测试性。
  • 它提高了对象图的可验证性(因为您不会依赖静态方法调用或服务定位器反模式)。

简而言之,将属性添加到控制器的视图模型并将其返回到视图。例如:

public class HomeController : Controller {
    private readonly ITranslator translator;
    public HomeController(ITranslator translator) {
        this.translator = translator
    }
    public ActionResult Index() {
        this.View(new HomeViewModel {
            WelcomeMessage = this.translator.Translate(TranslationEnum.WelcomeMessage)
        });
    }
}

您的观点如下:

@model HomeViewModel

<p>@Model.WelcomeMessage</p>

答案 1 :(得分:0)

首先,您的设计意图是错误的,因为它违反了单一的责任原则。为什么翻译依赖于存储库?

其次,为什么需要翻译,你可以使用asp.net全球化? click me我们不应该重新发明轮子。

第三,所有html助手都是必须是静态的扩展方法。

所以我的建议是,如果你必须使用翻译器,请重构翻译器类,将存储库与其分离,然后从那里创建扩展方法。

或者你可以使用全球化,开始时听起来很糟糕,但相信我并不像它看起来那么难。

public class Translator
{
    private static ITranslationRepository _repo;

    public static ITranslationRepository Repo
    {
         get { /*check null here before return*/ return _repo; } set { _repo = Repo; }
    }

    public Translator()
    {

    }

    public static string Translate(TranslationEnum translationEnum)
    {
        return _repo.GetTranslation(translationEnum, Session.LanguageId);
    }
}