使用Castle Windsor解析类而不注册它们

时间:2009-01-15 15:34:36

标签: .net castle-windsor unity-container prism

采取以下无用程序:

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一样。我没有在谷歌找到任何帮助我这样做的东西(虽然我的术语可能是错的)而且Windsor文档非常糟糕......

有人可以建议解决这个问题吗?

3 个答案:

答案 0 :(得分:9)

温莎目前不支持这一点,而且它是设计的。原因是你应该明确注册你需要的类型,这样你就不会得到配置错误的对象。

但是,有可能在不久的将来会在某个时刻添加一个钩子来创建非注册类型,因为这是WCF集成工具所需要的。 (编辑 - 它已在v2.1中添加 - 请查看ILazyComponentLoader s)

无论如何,无论懒惰的组件加载器如何,您可以做的最好的事情就是使用流畅的API批量注册所有类型,从一个符合您所需条件的程序集中预先填写。这不是更多的代码,你晚上睡得更好。

只有在启动时(在组合根中)确实没有足够的信息来确定您需要的组件时才使用延迟加载器。

答案 1 :(得分:6)

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 :(得分:2)

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;
    }
}