Вопрос по .net, dependency-injection – Как совместить проектируемые компоненты с внедрением зависимостей

9

При создании проектируемого компонента .NET вы должны предоставить конструктор по умолчанию. ОтIComponent документация:

To be a component, a class must implement the IComponent interface and provide a basic constructor that requires no parameters or a single parameter of type IContainer.

Это делает невозможным внедрение зависимости через аргументы конструктора. (Могут быть предоставлены дополнительные конструкторы, но дизайнер их игнорирует.) Некоторые альтернативы, которые мы рассматриваем:

Service Locator

Don't use dependency injection, instead use the service locator pattern to acquire dependencies. This seems to be what IComponent.Site.GetService is for. I guess we could create a reusable ISite implementation (ConfigurableServiceLocator?) which can be configured with the necessary dependencies. But how does this work in a designer context?

Dependency Injection via properties

Inject dependencies via properties. Provide default instances if they are necessary to show the component in a designer. Document which properties need to be injected.

Inject dependencies with an Initialize method

This is much like injection via properties but it keeps the list of dependencies that need to be injected in one place. This way the list of required dependencies is documented implicitly, and the compiler will assists you with errors when the list changes.

Есть идеи, какая лучшая практика здесь? Как ты делаешь это?

editЯ удалил & quot; (например, WinForms UserControl) & quot; так как я намеревался вопрос о компонентах в целом. Компоненты все об инверсии управления (см. Раздел 8.3.1UMLv2 specification) поэтому я не думаю, что «вы не должны вводить какие-либо услуги»; хороший ответ

edit 2: Потребовалось некоторое время, чтобы поиграть с WPF и шаблоном MVVM, чтобы, наконец, «получить» Отметьте ответ. Теперь я вижу, что визуальный контроль действительно является особым случаем. Что касается использования невизуальных компонентов на поверхностях конструктора, я думаю, что компонентная модель .NET принципиально несовместима с внедрением зависимостей. Похоже, что он разработан вместо шаблона поиска сервисов. Может быть, это начнет меняться с инфраструктурой, которая была добавлена в .NET 4.0 вSystem.ComponentModel.Composition Пространство имен.

Ваш Ответ

1   ответ
6

пока я не осознал, что думаю об этом неправильно. AFAIR, единственная причина создания реализации IComponent состоит в том, чтобы предоставить функции времени разработки - нет никакого эффекта времени выполнения реализаций IComponent.

Как следствие, это означает, что вы должны в основном создавать компоненты для реализации функций времени разработки. В частности, для элементов управления это означает, что вы можетеconfigure компонент вести себя определенным образом. Очень важно понимать, что это совершенно иная проблема, чем то, как компонент ведет себя на самом деле или какие данные он отображает. Он не должен иметь поведения во время разработки и не должен содержать данных.

Таким образом, ограничение на конструктор - это на самом деле благословение, так как оно инструктирует вас переосмыслить свой дизайн. Элемент управления - это независимое от источника данных программное обеспечение, которое отображает и взаимодействует с данными определенным образом. До тех пор, пока эти данные соответствуют определенным интерфейсам и т. Д., Контроль доволен.How получение данных не имеет значения для Контроля, и не должно быть. Было бы ошибкой позволить Control контролировать, как данные загружаются и изменяются.

В WPF это явно намного яснее, чем в Windows Forms: вы даете определенному элементу управления DataContext и привязываете свойства элемента управления к элементам этого DataContext. DataContext (который может быть любым объектом) происходит извне элемента управления; это ответственность или ваш уровень представления.

В Windows Forms вы все еще можете сделать то же самое, назначив контекст данных элементу управления. По сути, это инъекция собственности - просто знайте, что вы не должны внедрять сервисы; Вы должны ввестиdata.

Подводя итог, я бы не стал использовать ни одно из ваших предложений Вместо этого позвольте элементу управления иметь одно или несколько свойств, которые позволяют назначать данные элементу управления, и использовать привязку данных для привязки к этим данным. Внутри реализации элемента управления будьте готовы справиться с ситуацией, когда нет данных: это будет происходить каждый раз, когда элемент управления размещается в VS во время разработки. Шаблон Null Object очень полезен для реализации такой устойчивости.

Затем настройте контекст данных из ваших контроллеров. Это способ MVC сделать это: Control - это View, но у вас должен быть отдельный Controller, который может создавать экземпляры и назначать Model для View.

Да, я говорю, что элементы управления не должны использовать службы - службы должны использовать элементы управления. Элемент управления не должен делать ничего, кроме визуализации пользовательского интерфейса. Хорошо, что вы можете вводить причудливые стратегии сокращений, но такая логика принадлежит модели (представления), а не самому представлению. Затем вы можете привязать свой Просмотр к свойствам модели, которые выдают желаемые значения, вызывая введенные зависимости. Даже если вы, кажется, используете WinForms, проверьте это для вдохновения:msdn.microsoft.com/en-us/magazine/dd419663.aspx
Если я правильно интерпретирую ваш ответ, вы говорите, что средства управления не должны использовать какие-либо услуги. Я не уверен, что согласен. Например, у меня есть элемент управления, который не отображает текст напрямую, вызывая System.Windows.Forms.TextRenderer. Вместо этого он использует инъецируемую службу ITextRenderer (в основном с теми же методами). Это позволяет мне реализовывать причудливые стратегии аббревиатур, выходящие за рамки того, что предусмотрено платформой .NET, при этом сохраняя такой код независимым от самого элемента управления. Wim Coenen

Похожие вопросы