Возьмите следующую бесполезную программу:
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 ничего, что могло бы помочь мне в этом (хотя моя терминология может быть неправильной), а документация Виндзора довольно плохая ...
Может кто подскажет решение этой проблемы?
Я думаю, вы все еще получаете преимущество внедрения зависимостей в класс, даже если вы не используете интерфейс.
jishi: ответы на ваши вопросы нет и нет. Нет, это не противоречит цели IoC. Нет, он не отображает интерфейсы без их регистрации.





Windsor в настоящее время не поддерживает это, и это сделано специально. Причина в том, что вы должны явно регистрировать нужные вам типы, чтобы не получить неправильно сконфигурированный объект.
Однако существует вероятность того, что в какой-то момент в ближайшем будущем будет добавлен перехватчик для создания незарегистрированного типа, поскольку это необходимо для средства интеграции WCF. (Edit - он был добавлен в v2.1 - взгляните на ILazyComponentLoaders)
В любом случае, независимо от ленивых загрузчиков компонентов, лучшее, что вы можете сделать, - это использовать свободный API для пакетной регистрации всех типов из сборки, соответствующей вашим необходимым критериям. Это не намного больше кода, и вы будете спать лучше по ночам.
Используйте ленивые загрузчики только в том случае, если у вас действительно недостаточно информации при запуске (в вашем состав корень), чтобы определить, какие компоненты вам понадобятся.
Почему средство интеграции Windsor WCF должно создавать незарегистрированные типы?
@urig - чтобы вы могли говорить только о типах, указанных в вашем web.config, а не дублировать регистрацию в контейнере. СУХОЙ.
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>();
}
}
Это не полностью дублирует функциональность Unity - автоматически будет зарегистрирован только класс верхнего уровня. Что, если класс A зависит от конкретного класса B, ни A, ни B не зарегистрированы, и вы пытаетесь разрешить A? Unity справится с этим, но ваш код выше - нет.
Это правда. Однако во всех случаях, когда мне нужно было разрешить незарегистрированный тип, мне никогда не требовалось «рекурсивное» разрешение других незарегистрированных зависимостей, которые вы описываете. Это должно быть возможно реализовать и на Виндзоре, но лично мне в этом не было необходимости.
Кшиштоф, не бойтесь ссылаться на свой блог здесь :) 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;
}
}
Разве это не противоречит цели IoC? Если бы вы разрешили IProgram, найдет ли он определение класса, реализующего IProgram в этом случае?