Castle Windsor配置:从Assembly设置订单.装饰师目录

本文关键字:设置 配置 Windsor Assembly Castle | 更新日期: 2023-09-27 18:28:41

我有一个Windsor服务和两个实现它的组件:一个是"真实的"服务,另一个是将调用路由到"真实"服务或Web服务的"代理"(实现为装饰器)。

现在的理想情况是,如果找到了代理DLL,那么该代理将被用作装饰器。如果它不存在,所有呼叫都将直接转到"真实"服务。

我目前正在使用"FromAssembly.InDirectory"来注册组件,这就像一个魅力。然而,我认为这只是因为程序集恰好以正确的字母顺序命名,所以"真正的"服务是在"代理"(decorator)之前注册的。(如果我错了,请纠正我。)

这在我看来不是很结实。有没有更好的方法可以做到这一点,而无需在配置文件中手动配置每个组件?

我要么想要一个配置文件,只按正确的顺序列出程序集,然后这些文件中的所有组件都会自动注册(就像FromAssembly.Named一样)

或者——这会更好——一些机制可以自动确定哪个组件是装饰器(毕竟,它依赖于它实现的服务,而"真正的"服务没有),哪个是"真正的服务",然后自动按正确的顺序注册它们。

我当然可以自己实现后一种逻辑,但我不想重新发明轮子。

如有任何建议,我们将不胜感激。非常感谢。

编辑:这就是我到目前为止所拥有的。我如何确保默认组件(如果有装饰器,则为默认组件)得到命名,以便WCF工具可以通过其名称找到它?我的意思是,我可以向decorator部分添加一个"Named"调用,但如果没有定义decorator呢?

    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        var currDomain = AppDomain.CurrentDomain;
        var webAppBinDir = currDomain.RelativeSearchPath;
        var assemblyDir = (!string.IsNullOrEmpty(webAppBinDir)) ? webAppBinDir : currDomain.BaseDirectory;
        container.Register(
            Classes.FromAssemblyInDirectory(new AssemblyFilter(assemblyDir, Mask))
                   .Where(ImplementsServiceContract)
                   .WithServiceSelect((x, y) => GetServices(x))
                   .ConfigureIf(IsDecorator, c => c.IsDefault(y => IsDecorating(c, y)))
            );
    }
    private static bool ImplementsServiceContract(Type type)
    {
        return GetServices(type).Any();
    }
    private static IEnumerable<Type> GetServices(Type type)
    {
        return type.GetInterfaces().Where(IsServiceContract);
    }
    private static bool IsServiceContract(Type type)
    {
        var ns = type.Namespace;
        return ns != null && ns.StartsWith(NamespacePrefix) && Attribute.IsDefined(type, typeof(ServiceContractAttribute));
    }
    private static bool IsDecorator(ComponentRegistration c)
    {
        Type component = c.Implementation;
        return GetServices(component).Any(x => IsDecorating(c, x));
    }
    private static bool IsDecorating(ComponentRegistration c, Type service)
    {
        Type component = c.Implementation;
        return service.Assembly != component.Assembly;
    }

Castle Windsor配置:从Assembly设置订单.装饰师目录

我在这个场景中的旧方法是在web.config或专用xml文件中注册声明符。自3.1版本以来,您可以为给定的接口指定一个Default组件:使用命名约定策略将decorator设置为默认组件变得非常容易,无论具体注册如何。

我用来确保注册顺序的另一种方法是创建InstallerFactory,这样您就可以轻松地驱动安装程序的执行顺序,而不仅仅是为装饰程序。

很抱歉,如果我没有提供任何代码示例。。。但我现在正在度假

为装饰器使用IsDefault

doco

如果您没有对该程序集的引用(为什么不呢?),那么使用.ConfigureIf并以某种方式(可能是通过名称)匹配类型