Разрешение классов без их регистрации с помощью Castle Windsor

Возьмите следующую бесполезную программу:

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer unityContainer = new UnityContainer();
        IWindsorContainer windsorContainer = new WindsorContainer();

        Program unityProgram = unityContainer.Resolve<Program>();
        Program castleProgram = windsorContainer.Resolve<Program>();
    }
}

UnityContainer вернет мне экземпляр Program, а контейнер Windsor выдаст исключение ComponentNotFoundException.

Я вижу аргументы в пользу обоих вариантов поведения и не возражаю против того, что у меня получилось, однако Prism V2 Drop 8 (последний на момент написания) полагается на поведение Unity внутри себя, запрашивая классы, которые не были зарегистрированы.

Вместо того, чтобы находить и регистрировать все эти классы для Prism, я бы предпочел просто заставить Windsor вести себя как Unity. Я не нашел в Google ничего, что помогло бы мне это сделать (хотя моя терминология может быть неправильной), а документация Виндзора довольно плохая ...

Может кто подскажет решение этой проблемы?


person James Thurley    schedule 15.01.2009    source источник
comment
Разве это не противоречит цели IoC? Если бы вы разрешили IProgram, найдет ли он определение класса, реализующего IProgram в этом случае?   -  person jishi    schedule 15.01.2009
comment
Я предполагаю, что вы по-прежнему получаете преимущество внедрения зависимостей в класс, даже если вы не используете интерфейс.   -  person James Thurley    schedule 15.01.2009
comment
jishi: ответы на ваши вопросы нет и нет. Нет, это не противоречит цели IoC. Нет, он не отображает интерфейсы без их регистрации.   -  person Anthony    schedule 28.12.2009


Ответы (3)


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

Однако существует вероятность того, что в какой-то момент в ближайшем будущем будет добавлен перехватчик для создания незарегистрированного типа, поскольку это необходимо для средства интеграции WCF. (Edit - он был добавлен в v2.1 - взгляните на ILazyComponentLoaders)

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

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

person Krzysztof Kozmic    schedule 31.01.2009
comment
Почему средство интеграции Windsor WCF должно создавать незарегистрированные типы? - person urig; 21.06.2009
comment
@urig - чтобы вы могли указать типы, указанные только в вашем web.config, а не дублировать регистрацию в контейнере. СУХОЙ. - person Krzysztof Kozmic; 22.06.2009

Windsor не поддерживает это из коробки, но вы можете создать для этого методы расширения:

static class WindsorExtensions
{
    public static object ResolveType(this IWindsorContainer container, Type type)
    {
        if ( type.IsClass && !container.Kernel.HasComponent(type) )
            container.Kernel.AddComponent(type.FullName, type, LifestyleType.Transient);
        return container.Resolve(type);
     }

     public static T ResolveType<T>(this IWindsorContainer container)
     { return (T)ResolveType(container, typeof(T)); }
}

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer unityContainer = new UnityContainer();
        IWindsorContainer windsorContainer = new WindsorContainer();

        Program unityProgram = unityContainer.Resolve<Program>();
        Program castleProgram = windsorContainer.ResolveType<Program>();
    }
}
person Bojan Resnik    schedule 24.02.2009
comment
Это не полностью дублирует функциональность Unity - автоматически будет зарегистрирован только класс верхнего уровня. Что, если класс A зависит от конкретного класса B, ни A, ни B не зарегистрированы, и вы пытаетесь разрешить A? Unity справится с этим, но ваш код выше - нет. - person Anthony; 01.02.2010
comment
Это правда. Однако во всех случаях, когда мне нужно было разрешить незарегистрированный тип, мне никогда не требовалось рекурсивное разрешение других незарегистрированных зависимостей, которые вы описываете. Должно быть возможно реализовать это и на Виндзоре, но лично мне в этом не было необходимости. - person Bojan Resnik; 01.02.2010

Кшиштоф, не бойтесь ссылаться на свой блог здесь :) http://devlicious.com/blogs/krzysztof_kozmic/archive/2009/11/16/castle-windsor-lazy-loading.aspx

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

public class ViewModelLoader : Castle.MicroKernel.Resolvers.ILazyComponentLoader {
    public IRegistration Load(string key, Type service)
    {
        if (service == null)
            return null;
        if (service.Name.EndsWith("ViewModel", StringComparison.CurrentCultureIgnoreCase))
            return Component.For(service).Named(key);
        else
            return null;
    }
}
person jrwren    schedule 11.10.2010