C# Castle Windsor配置:为装饰程序设置FromAssembly.InDirectory的顺序

C# Castle Windsor配置:为装饰程序设置FromAssembly.InDirectory的顺序,c#,.net,reflection,castle-windsor,decorator,C#,.net,Reflection,Castle Windsor,Decorator,我有一个Windsor服务和两个实现它的组件: 一个是“真正的”服务,另一个是将调用路由到“真正的”服务或Web服务的“代理”(实现为decorator) 现在理想的情况是,如果找到代理DLL,代理将用作装饰器。 如果它不存在,所有呼叫都将直接转到“真正的”服务 我目前正在使用“fromsassembly.InDirectory”来注册组件,这就像一个符咒。 然而,我认为这只会起作用,因为程序集恰好是按照正确的字母顺序命名的,所以“真正的”服务是在“代理”(decorator)之前注册的。 (如

我有一个Windsor服务和两个实现它的组件: 一个是“真正的”服务,另一个是将调用路由到“真正的”服务或Web服务的“代理”(实现为decorator)

现在理想的情况是,如果找到代理DLL,代理将用作装饰器。 如果它不存在,所有呼叫都将直接转到“真正的”服务

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

在我看来,这不太可靠。 有没有更好的方法不用手动配置配置文件中的每个组件就可以做到这一点

我想要一个配置文件,在该文件中我只按正确的顺序列出程序集,并且这些文件中的所有组件都将自动注册(就像fromsassembly.Named一样)

或者——这会更好——某种机制,自动找出哪个组件是装饰器(毕竟,它依赖于它实现的服务,而“真正的”服务不依赖),以及哪个组件是“真正的服务”,然后按照正确的顺序自动注册它们

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

如有任何建议,将不胜感激。 谢谢大家!

编辑: 这就是我目前所拥有的。 如何确保命名默认组件(如果有装饰器,则为默认组件),以便WCF设施可以通过其名称找到它? 我的意思是,我可以向decorator部分添加一个“命名”调用,但是如果没有定义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;
    }
public void安装(IWindsorContainer,IConfigurationStore)
{
var currDomain=AppDomain.CurrentDomain;
var webAppBinDir=currDomain.RelativeSearchPath;
var assemblyDir=(!string.IsNullOrEmpty(webAppBinDir))?webAppBinDir:currDomain.BaseDirectory;
集装箱。登记(
Classes.FromAssemblyIndirector(新的AssemblyFilter(assemblyDir,掩码))
.何处(实施服务合同)
.WithServiceSelect((x,y)=>GetServices(x))
.ConfigureIf(IsDecorator,c=>c.IsDefault(y=>isDecorrating(c,y)))
);
}
私有静态bool实现服务契约(类型)
{
返回GetServices(type).Any();
}
私有静态IEnumerable GetServices(类型)
{
返回类型.GetInterfaces().Where(IsServiceContract);
}
专用静态布尔IServiceContract(类型)
{
var ns=type.Namespace;
返回ns!=null&&ns.StartsWith(NamespacePrefix)&&Attribute.IsDefined(type,typeof(ServiceContractAttribute));
}
专用静态布尔IsDecorator(组件注册c)
{
类型组件=c.实现;
返回GetServices(component).Any(x=>isDecorrating(c,x));
}
专用静态布尔ISDecorrating(组件注册c,类型服务)
{
类型组件=c.实现;
return service.Assembly!=组件.Assembly;
}

对于这个场景,我以前的方法是在web.config或专用xml文件中注册声明器。 从3.1版开始,您可以为给定的接口指定一个默认组件:使用命名约定策略将装饰器设置为默认组件变得非常容易,不管具体的注册是什么

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


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

使用
IsDefault
作为装饰师


如果您没有对该程序集的引用(为什么没有?),请使用
.ConfigureIf
,并以某种方式(可能通过名称)匹配类型您能详细说明一下这个“默认组件”吗?我应该把它放在哪里?你说的是“后备组件”(fallbackcomponents)吗?这对装饰师有帮助吗?我可以在一次调用中对所有组件使用它,还是仍然需要配置每个组件?search for Component现在可以“强制”成为其服务的默认组件,而不需要是第一个注册的组件,但decorator不应该是第一个注册的组件吗?官方文档提到使用IHandlerSelector指定订单:但我不太确定这是否是我想要的。我有一个实现服务的组件和一个decorator(每个服务-所以它可能总共有10个decorator左右)。我只想让装饰程序“包装”/“装饰”默认组件,而不使用任何解析循环和尽可能少的配置。如果您确实需要实现装饰程序模式,windsor将不使用额外的配置来处理它,以防止循环问题。最简单的场景是有两个组件实现相同的接口。decorator实现将具有与接口实例相同的构造函数依赖关系。Windsor使用为该接口注册的早期组件,但使用当前组件以避免循环问题。IsDefault配置我建议您不是针对实现相同接口的嵌套组件,而是针对依赖于其他组件的接口Hanks!如何使其尽可能健壮且易于配置?如果包含程序集存在,我希望正确注册装饰程序。但是fromsassembly.InDirectory依赖于字母顺序,不是吗?我是否应该编写自己的InstallerFactory?根据我的回答,如果您使用IsDefault,则不再需要InstallerFactoryT