0

Примечание. Для уточнения этого вопроса речь не идет о настройке IoC в контроллерах MVC, а вне их.Windsor Typed Factory - классы внешнего контроля класса IoC

У меня IoC отлично работает в моих контроллерах, однако мне нужно, чтобы он работал вне контроллера в пользовательских классах (в классе CacheManager, который использует список CacheBuilders для создания кеша).

Для этого до сих пор я передавал ссылку контейнера Windsor в CacheManager, а CacheManager передавал его каждому CacheBuilder для разрешения любых ссылок, которые могут потребоваться для решения. Однако я считаю, что это не очень хорошая идея, и я хочу сделать это, не переходя в эту ссылку и из того, что я прочитал, я думаю, что набранные фабрики могут помочь мне в этом.

Я создал интерфейс, как показано ниже ...

public interface ITypeFactory 
{ 
    T Create<T>(); 
    void Release(object value); 
} 

... и зарегистрировал его как тип для завода в методе BootStrapContainer который получает обожженного при запуске веб-приложение ....

container.AddFacility<TypedFactoryFacility>(); 
container.Register(Component.For<ITypeFactory>().AsFactory()); 

Теперь я намерен использовать это как следующий в одном из моих CacheBuilders ...

public class CountryCacheBuilder : ICacheBuilder 
{ 
    public ITypeFactory TypeFactory { get; set; } 

    public void PersistToCache(Cache cache) 
    { 
     var repository = TypeFactory.Create<ICountryRepository>(); 

     var listOfCountries = repository.GetAllCountries(); 

     // add list of Countries to cache 
    } 
} 

... данный ICountryRepository определен ниже ....

public interface ICountryRepository 
{ 
    List<Country> GetAllCountries(); 
} 

... и в методе Global.asax App_Start зарегистрировать все CacheBuilders с CacheManager как так ...

CacheManager.Instance.CacheBuilders.Add(new CountryCacheBuilder()); 

а затем вызвать

CacheManager.BuildCache() 

который только перебирает список CacheBuilders и увольняет PersistToCache для каждого из них.

Однако в методе CountryCacheBuilder.PersistToCache я вижу, что свойство TypeFactory равно null, когда я ожидал его создания. Может ли кто-нибудь сказать мне, что мне здесь не хватает? Нужно ли мне указывать контейнеру, как создавать каждый CacheBuilder?

ответ

1

Я проходил ссылку контейнера Виндзор в CacheManager ... Я считаю, что это не очень хорошая идея

Вы правы; это не очень хорошая идея. Вы в основном используете Service Locator anti-pattern.

Я создал интерфейс, как показано ниже ...

Вы просто создали абстракции для IoC контейнера, который до сих пор является реализация Service Locator антишаблоном. Другими словами, все еще плохая идея.

Вместо инъекции ITypeFactory вы должны просто вводить зависимости, которые требуется классу.Кроме того, вы не должны использовать вложение свойств, потому что Castle Windsor все равно будет создавать для вас класс, даже если его зависимости не могут быть разрешены (он просто пропускает свойства, которые невозможно вставить). Это звучит неплохо, но скорее вы хотите, чтобы приложение быстро вышло из строя, вместо того, чтобы разрешить контейнеру возвращать экземпляр, который нельзя использовать (так как большинство зависимостей обычно требуется для работы класса).

Это, как вы CountryCacheBuilder должны выглядеть следующим образом:

public class CountryCacheBuilder : ICacheBuilder 
{ 
    private readonly ICountryRepository repository; 

    public CountryCacheBuilder(ICountryRepository repository) 
    { 
     this.repository = repository; 
    } 

    public void PersistToCache(Cache cache) 
    { 
     var listOfCountries = this.repository.GetAllCountries(); 

     // add list of Countries to cache 
    } 
} 

замок Виндзор (и любой другой IoC контейнер по этому вопросу) будут анализировать конструктор класса и вводить его зависимость. И не только вы должны применять шаблон внедрения конструктора для этого типа, но также и для его зависимостей и его потребителей. Например, ваш контроллер может выглядеть так:

public class CountryController : Controller 
{ 
    private readonly ICacheBuilder cacheBuilder; 

    public CountryController(ICacheBuilder cacheBuilder) 
    { 
     this.cacheBuilder = cacheBuilder; 
    } 

    public ActionResult Index() 
    { 
     // ... 
    } 
} 

По умолчанию MVC создаст для вас классы контроллеров, а не Castle. Вам нужно будет redirect the creation to Castle.

+0

На самом деле, почему я задаю этот вопрос, это потому, что я не создаю CountryCacheBuilder изнутри контроллера. Это созданный им CacheManager (который также вызывается __not__ с любого контроллера, а затем вызывается из метода App_Start в Global.asax). –

Смежные вопросы