2012-05-02 3 views
3

Привет, я новичок в Castle Windsor и изо всех сил пытаюсь понять некоторые из основополагающих принципов, поэтому я решил, что я отправляю вопрос, а не просматриваю код в надежде решить проблему раньше ,Custom config injection - New to Castle Windsor/IoC

У меня есть веб-служба, которая должна извлекать информацию из файла конфигурации web.config. Эта информация находится в настраиваемом разделе конфигурации, и мне интересно, как я могу получить эту информацию в соответствующем классе. Я не хочу привязывать этот класс к файлу конфигурации, поскольку я могу разместить его через IIS или пользовательскую службу Windows. Моя первая попытка была сделать что-то вроде этого:

iocCon.Register(Component.For<ErrorMessagesSection>().LifeStyle.Singleton.Instance(FindConfigSection<ErrorMessagesSection>())); 

private T FindConfigSection<T>() where T : ConfigurationSection 
    { 
     System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("/web.config");//TODO: remove this hard coding to iis hosting .OpenExeConfiguration(ConfigurationUserLevel.None); 
     ConfigurationSectionGroupCollection sectionGroups = config.SectionGroups; 

     foreach (ConfigurationSectionGroup sectionGroup in sectionGroups) 
      foreach (ConfigurationSection configurationSection in sectionGroup.Sections) 
       if (configurationSection.GetType() == typeof(T)) 
        return (T) configurationSection; 
     return null; 
    } 

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

UGLY_HACK = new ConfigFileErrorMessageManager(eMessages); 
iocContationer.Register(Component.For<IErrorMessageManager>().ImplementedBy<ConfigFileErrorMessageManager>().LifeStyle.Singleton.Instance(UGLY_HACK)); 

это первая регистрация только что созданного контейнера и она взрывается со следующим:

[ComponentRegistrationException: This component has already been assigned implementation xxx.ConfigFileErrorMessageManager] 
Castle.MicroKernel.Registration.ComponentRegistration`1.ImplementedBy(Type type,  IGenericImplementationMatchingStrategy genericImplementationMatchingStrategy) +310 

Castle.MicroKernel.Registration.ComponentRegistration`1.Instance(TService instance) +44 

Мой первый вопрос: как возможно эта ошибка (ничего не было зарегистрировано)/или это означает что-то более тонкое, чем кажется? Второй вопрос: какова наилучшая практика получения информации о конфигурации тем классам, которые в ней нуждаются (неужели я ошибаюсь)?

Спасибо за вашу помощь

ответ

4

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

Here's an IConfigurationManager implementation с адаптером для WebConfigurationManager, который позволит вам сделать именно это.

Чтобы зарегистрировать его

container.Register(
    Component.For<IConfigurationManager>() 
      .Instance(new WebConfigurationManagerAdapter())); 

Теперь вы можете вводить IConfigurationManager на компоненты, которые должны получить доступ к конфигурации.

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

container.Register(
    Component.For<ErrorMessagesSection>() 
      .UsingFactoryMethod(kernel => 
       kernel.Resolve<IConfigurationManager>() 
         .GetSection<ErrorMessagesSection>("errorSectionName"))); 
+1

Спасибо, Russ. Мне нравится эта идея больше, чем то, что я делаю, и поэтому я внес изменения, а после внесения некоторых изменений я получил все это. Я бы очень хотел понять ошибку, которую я получил, хотя мне не нравится не понимать, почему что-то произошло, и у меня действительно нет времени пахать через источник ветра, поэтому, если у вас есть мысли об ошибке, я бы их оценил , –

+0

@ Направьте ошибку, которую вы получаете, обращается ко мне с тем, что вы используете как «ImplementedBy <>», так и «Instance()» для регистрации компонента для службы «IErrorMessageManager», когда на самом деле вам нужен только один (и, следовательно, сообщение об исключении, относящееся к нескольким регистрациям). Похоже, вам нужен только 'Instance()', который по соглашению зарегистрирует прошедший экземпляр как singleton. –

+1

Вот и все. Большое спасибо. –