Разрешение классов без регистрации их с помощью Castle Windsor - PullRequest
17 голосов
/ 15 января 2009

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

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 вернет мне экземпляр программы, где контейнер Windsor будет генерировать исключение ComponentNotFoundException.

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

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

Может кто-нибудь предложить решение этой проблемы?

Ответы [ 3 ]

9 голосов
/ 01 февраля 2009

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

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

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

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

6 голосов
/ 24 февраля 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>();
    }
}
2 голосов
/ 11 октября 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;
    }
}
...