Внедрение пользовательской конфигурации - Новое в Castle Windsor / IoC

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

У меня есть веб-сервис, который должен извлекать информацию из файла конфигурации 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

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

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


person Justin_H    schedule 02.05.2012    source источник


Ответы (1)


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

Вот IConfigurationManager реализация с адаптером для 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")));
person Russ Cam    schedule 02.05.2012
comment
Спасибо, Расс, мне эта идея нравится больше, чем то, что я делал, поэтому я внес изменения, и после внесения других изменений у меня все заработало. Я действительно хотел бы понять ошибку, которую я получил, но мне не нравится не понимать, почему что-то произошло, и у меня действительно нет времени, чтобы пробираться через источник Windsor, поэтому, если у вас есть какие-либо мысли об ошибке, я был бы признателен им . - person Justin_H; 03.05.2012
comment
@ Просто ошибка, которую вы получаете, как мне кажется, связана с тем фактом, что вы используете как ImplementedBy<>, так и Instance() для регистрации компонента для службы IErrorMessageManager, хотя на самом деле вам нужен только один (и, следовательно, сообщение об исключении, относящееся к множественным регистрациям) . Похоже, вам нужен только Instance(), который по соглашению зарегистрирует переданный экземпляр как синглтон. - person Russ Cam; 04.05.2012
comment
Вот и все. Большое спасибо, Расс. - person Justin_H; 04.05.2012