Можно ли регистрировать компоненты в Виндзоре без указания интерфейса? - PullRequest
15 голосов
/ 28 июня 2010

Считается ли плохой формой регистрация компонентов в Виндзоре без указания интерфейса?то есть

container.Register(Component.For<MyClass>().LifeStyle.Transient);

в отличие от ...

container.Register(Component.For<IMyClass>().ImplementedBy<MyClass>().LifeStyle.Transient);

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

1 Ответ

26 голосов
/ 28 июня 2010

Да, было бы хорошо зарегистрировать компоненты без их интерфейсов, но не по той причине, которую вы указали .

Конкретные зависимости

Может случиться так, что компоненты зависят от конкретных классов.Например, в Entity Framework потребителям должен быть введен ObjectContext.Это конкретный класс, который все еще должен быть внедрен, потому что он должен быть общим для нескольких потребителей.

Таким образом, с учетом конструктора потребителя, подобного этому:

public FooRepository(FooObjectContext objectContext)

youпотребуется настроить контейнер следующим образом:

container.Register(Component.For<FooObjectContext>());

FooRepository не запрашивает интерфейс , поэтому нет смысла регистрировать интерфейс (даже если он был доступен), но вы все равно должны зарегистрироватьсяконкретный класс, потому что Виндзор может разрешать только типы, явно зарегистрированные .

Интерфейсы только с одной реализацией

Тогда как насчет интерфейсов только с одной реализацией?Еще раз, потребитель решает требования.

Представьте, что у потребителя есть этот конструктор:

public Ploeh(IBar bar)

Единственный способ, которым Castle Windsor сможет разрешить Ploeh, - это когда вы зарегистрируете IBar.Даже если Bar является единственной реализацией IBar, это не будет работать :

container.Register(Component.For<Bar>());

Это не работает, потому что IBar никогда не регистрируется.Каслу Виндзору все равно, что в Bar реализован IBar, потому что он не хочет стараться быть умным от вашего имени.Вы должны указать это явно:

container.Register(Component.For<IBar>().ImplementedBy<Bar>());

Это отображает IBar на Bar.

Регистрация интерфейсов и конкретных типов

Тогда что, если вы хотите иметь возможность разрешать как конкретный тип, так и интерфейс?

Проблема с предыдущим примером состоит в том, что он позволит вам разрешить IBar, но не Bar.

Вы можете использовать метод Forward или мульти-универсальную перегрузку For для пересылки регистраций:

container.Register(Component.For<Bar, IBar>().ImplementedBy<Bar>());

Это позволяет вам разрешить и Bar и IBar.

...