Разрешение классов без регистрации их с помощью 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 вернет мне экземпляр программы, где, поскольку контейнер Windsor будет вызывать исключение ComponentNotFoundException.
Я могу видеть аргументы для обоих типов поведения и не возражаю против того, что у меня получится, однако Prism V2 Drop 8 (последний на момент написания) полагается на поведение Unity внутри, запрашивая классы, которые не были зарегистрированы.
Вместо того, чтобы находить и регистрировать все эти классы для Prism, я бы скорее просто заставил Windsor вести себя как Unity. Я ничего не нашел в google, чтобы помочь мне сделать это (хотя моя терминология может быть неправильной), а документация Windsor довольно плохая...
Может ли кто-нибудь предложить решение этой проблемы?
Ответы
Ответ 1
Windsor в настоящее время не поддерживает это, и он по дизайну. Причиной является то, что вы должны явно регистрировать типы, которые вам нужны, чтобы вы не получили неправильно сконфигурированный объект.
Однако есть вероятность, что в ближайшем будущем в какой-то момент будет добавлен крючок для создания незарегистрированного типа, поскольку это необходимо для интеграции интеграции WCF. (Edit - добавлено в v2.1 - посмотрите ILazyComponentLoader
s)
В любом случае, независимо от ленивых загрузчиков компонентов, лучше всего использовать свободный API для пакетного регистрации всех типов из сборки, соответствующей вашим необходимым критериям. Это не намного больше кода, и вы будете лучше спать по ночам.
Используйте ленивые загрузчики, только если у вас действительно недостаточно информации при запуске (в корне вашего состава), чтобы определить, какие компоненты вам понадобятся.
Ответ 2
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>();
}
}
Ответ 3
Krzysztof не бойтесь ссылаться на свой собственный блог здесь. 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;
}
}