2015-07-22 4 views
1

Я работаю с интерфейсами в первый раз, чтобы создать свободно связанный код. В одном из моих классов у меня есть следующий конструктор:Мгновенный интерфейс, когда null

public ExceptionHandler(string logLocation = null, ICanLocalize localizer = null) 

радиомаяк в этом конструкторе не является обязательным и является недействительным по умолчанию (так как не все хотят, чтобы локализовать этот класс). Прямо сейчас у меня есть класс Localizer, который реализует этот интерфейс. Этот класс имеет конструктор с параметрами для полной функциональности и конструктор без параметров для базовой проверки нуля. Я имею в виду, что оба конструктора устанавливают bool, который указывает, правильно ли инициализирован класс. Если это не (пустой конструктор), значения по умолчанию будут возвращены без их локализации.

Так что в моем коде я могу

_localizer.GetString("key", "optional fallback value"); 

В случае, если должным образом инициализирован это вернет «ключ» на английском или «Sleutel» на голландском языке. Если он не был правильно инициализирован, возвращается «дополнительное резервное значение» (или key, если не было задано значение возврата). Для того, чтобы добиться такого поведения я следующий в конструкторе ExceptionHandler:

_localizer = localizer ?? new Localizer(); 

Это, очевидно, плотно пары классов вместе снова, не то, что было задумано. Я обнаружил, что сделал это после рефакторинга моего класса Localizer, чтобы иметь предполагаемое поведение.

Теперь одним из решений я хотел добавить localizer.CreateLocalizer() к интерфейсу, который использует пустой конструктор в классе Localizer. К сожалению, это не имеет смысла, поскольку исключение будет выбрано потому, что localizer имеет значение NULL. Другой подход, который я пытался, заключался в добавлении статического метода в интерфейс, но это также не удалось, поскольку интерфейсы не могут иметь статику.

Прямо сейчас я не знаю, как я могу решить эту проблему. Является ли мой единственный вариант проверить в ExceptionHandler, если localizer является нулевым и предвидит его внутри этого класса или есть другое решение, о котором я еще не думал? Как насчет заводов, есть ли у них использование здесь и как это влияет на сцепление моего кода?

ответ

1

По моему скромному мнению, вы не должны повторно изобретать квадратное колесо, а использовать существующее колесо. То, что вы пытаетесь сделать, называется dependency injection. И, вероятно, вы должны узнать о inversion of control тоже.

А как насчет использования фрейма как Castle Windsor?

WindsorContainer container = new WindsorContainer(); 
container.Register(Component.For<IExceptionHandler>().ImplementedBy<ExceptionHandler>()); 
container.Register(Component.For<ILocalizer>().ImplementedBy<Localizer>()); 

IExceptionHandler handler = container.Resolve<IExceptionHandler>(); 

// If there's a constructor with a registered component it will inject 
// it automatically, so if you set the injected ILocalizer to a public property 
// of the IExceptionHandler implementation constructor, you'll get the defined 
// implementation for your localizer! 
handler = container.Localizer; 

Существует много вариантов. Например, Ninject.