Практика для регистрации типов с контейнером IoC? - PullRequest
3 голосов
/ 21 февраля 2011

У меня есть решение с несколькими проектами (MyApp.Data, MyApp.BLL, MyApp.Web).Я регистрирую типы в файле Global.asax в MyApp.Web (основное веб-приложение):

builder.RegisterType<SomeService1>().As<ISomeService1>().InstancePerHttpRequest();
builder.RegisterType<SomeService2>().As<ISomeService2>().InstancePerHttpRequest();
//...etc

И мне интересно, является ли плохой практикой регистрация типов и их области действия с использованием атрибутов в других сборках (например,, в MyApp.BLL).Смотрите ниже:

[Dependency(typeof(ISomeService1), ComponentLifeStyle.Transient)]
public class SomeService1 : ISomeService1
{
   //methods and properties go here
}

Ответы [ 2 ]

3 голосов
/ 21 февраля 2011

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

Кроме того, это может ограничить ваши будущие возможности. Например, если вы указываете область жизни, вы не можете повторно использовать службу с другой областью действия.

Как правило, вы должны составить приложение в Composition Root (global.asax), что дает вам одно местоположение с четко определенной ответственностью где все классы составлены.

Это было бы намного более управляемым и обслуживаемым , который распространял бы данные конфигурации по всем вашим классам.

2 голосов
/ 21 февраля 2011

Как показывает ваш вопрос, имеет смысл делегировать ответственность за регистрацию сборке, которая знает, что нужно зарегистрировать. Например, если вы используйте библиотеку SolrNet , она предоставляет метод, который выполняет регистрацию компонентов, чтобы инкапсулировать знания о том, что необходимо зарегистрировать, и избавить потребителя библиотеки от необходимости изучать все о библиотеке перед началом работы.

Однако при таком подходе существует потенциальная проблема. Изменились бы ваши требования к регистрации, если бы вы использовали зависимые сборки в других приложениях? Например, имеет ли смысл регистрировать что-то как ComponentLifeStyle.HttpRequestScoped и затем использовать это в не-веб-приложении? Передавая регистрацию зависимости, вы связываете зависимость с требованиями регистрации ее потребителя (и с выбором контейнера IoC).

Autofac (я не могу говорить о других контейнерах IoC) предоставляет способ обойти это. Это позволяет вам переопределить регистрации, чтобы последний зарегистрированный компонент использовался при разрешении службы. Это означает, что вы можете вызвать метод регистрации библиотеки, а затем зарегистрировать свои собственные службы, чтобы переопределить значения по умолчанию.

Существует еще одна проблема с предложенной вами регистрацией на основе атрибутов - она ​​не позволяет указать лямбда-выражение в качестве создателя компонента. Как бы вы реализовали такую ​​регистрацию с атрибутами?

builder.Register(c => new A(c.Resolve<B>()));

Может быть предпочтительнее определить интерфейс IRegistrar, а затем использовать отражение, чтобы искать во всех загруженных сборках реализации и вызывать их. Возможно, что-то вроде этого:

public interface IRegistrar
{
    void RegisterComponents();
}
...