17

采取以下无用程序:

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。我在谷歌上没有找到任何可以帮助我做到这一点的东西(尽管我的术语可能是错误的)而且温莎文档非常糟糕......

任何人都可以提出解决这个问题的方法吗?

4

3 回答 3

9

Windsor 目前不支持这一点,这是设计使然。原因是您应该显式注册所需的类型,以免得到错误配置的对象。

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

无论如何,不​​管惰性组件加载器如何,您能做的最好的事情就是使用 fluent API 来批量注册符合您所需条件的程序集中的所有类型。代码不多,你晚上会睡得更好。

仅当您在启动时(在您的组合根目录中)确实没有足够的信息来确定您需要哪些组件时才使用惰性加载器。

于 2009-01-31T22:10:40.613 回答
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>();
    }
}
于 2009-02-24T15:49:39.617 回答
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;
    }
}
于 2010-10-11T15:52:25.283 回答