0

Я хотел бы создать ViewHelper для локализации моего приложения ASP.NET MVC. Что-то вроде этого:ASP.NET MVC ViewHelpers и Injection Dependency

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) View выглядит следующим образом:

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

Теперь проблема, конечно, я не могу сделать метод Translate статичны, потому что мне нужно, чтобы получить доступ к переменная экземпляра _repo.

Как я могу вставить репозиторий в ViewHelper, чтобы я мог использовать его в представлении, как показано выше?

ответ

0

Прежде всего, намерение вашего дизайна ошибочно, поскольку оно нарушает принцип единой ответственности. Почему переводчик зависит от репозитория?

Во-вторых, зачем вам нужен переводчик, вы можете использовать asp.net-глобализацию? click me Мы не должны изобретать велосипед.

В-третьих, все html-помощники - это методы расширения, которые должны быть статическими.

так что я хочу сказать, что если вам нужно использовать переводчик, пожалуйста, отредактируйте класс Translator, отделите репозиторий от него, а затем создайте методы расширения оттуда.

или вы можете использовать глобализацию, это звучит ужасно, но, поверьте, это не так сложно, как кажется.

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); 
    } 
} 
+0

Как что SRP нарушение? Переводчик несет в себе одну ответственность: он берет ключ и возвращает значение для этого ключа в соответствии с логикой внедренной реализации ITranslationRepository. Меня не волнует, что в конечном итоге реализация использует ASP.NET Globalization, базу данных или даже веб-сервис. – Sandro

+0

, если он берет ключ и возвращает строку, почему вы проходите в репозитории? Хорошо, вам нужен репозиторий для извлечения ключа, но это не переводчик. – Larry

+0

Не думайте о репозитории базы данных. «ITranslationRepository» - это просто интерфейс. Я мог бы также назвать его «ITranslationService» или «ITranslationHelper». Я абстрагирую логику получения от моего помощника, чтобы я мог изменить ее в любое время. – Sandro

3

Ответственность за просмотр - это просто преобразовать данные, возвращаемые с контроллера в структуру HTML. Взгляды сложны (чтобы невозможно), чтобы их можно было проверить автоматически, поэтому лучше всего держать их настолько тупыми, насколько это возможно.

Вместо использования Translator, на ваш взгляд, введите его в контроллер и позвольте контроллеру вызывать Translator. Это решает целый ряд проблем:

  • Он сохраняет вид простым.
  • Это улучшает ремонтопригодность.
  • Это улучшает тестируемость.
  • Это улучшает проверяемость графиков объектов (потому что вы не отступаете от вызовов статических методов или анти-шаблона Service Locator).

Короче говоря, добавьте свойство модели представления контроллера и верните это в представление. Пример:

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> 
+0

Вот что я пробовал в первую очередь. Но я не могу получить доступ к свойству Controller из представления, или я что-то пропустил? – Sandro

+0

@Sandro: представление ничего не должно знать о контроллере и наоборот. См. Мое обновление. – Steven

+0

Я вижу, но это невозможно для этого проекта. В некоторых представлениях мы даже используем модель Entity как модель. Это действительно единственный способ? Я имею в виду, что это требует нескольких шагов больше, чем с помощью ViewHelper и с большим количеством переводов ... pheew – Sandro