1

I have a Windsor service and two components implementing it: One being the "real" service, and one being a "proxy" (implemented as a decorator) that routes the call either to the "real" service, or to a webservice.

Now the ideal situation would be that if the proxy DLL was found, the proxy would be used as a decorator. And if it doesn't exist, all calls would go directly to the "real" service.

I'm currently using "FromAssembly.InDirectory" to register the components, and this works like a charm. However, I think this only works because the assemblies happen to be named in the correct alphabetic order, so that the "real" service is registered before the "proxy" (decorator). (Please correct me if I'm wrong.)

This doesn't look very robust to me. Is there a better way to do it without manually configuring every single component in a config file?

I'd either like a configuration file where I would only list the assemblies in the correct order, and all components from those files would be registered automatically (just like FromAssembly.Named).

Or - and that would be even better - some mechanism that automatically figures out which component is the decorator (after all, it has a dependency on the service it implements, whereas the "real" service doesn't), and which one is the "real service", and then automatically registers them in the correct order.

I could of course implement the latter logic myself, but I don't want to reinvent the wheel.

Any suggestions will be highly appreciated. Thank you!

Edit: This is what I have so far. How can I make sure the default component (the decorator, if there is one, the default component otherwise) gets named, so that the WCF facility can find it by its name? I mean, I could just add a "Named" call to the decorator part, but what if there are no decorators defined?

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

2 回答 2

1

用于IsDefault装饰器

多可

如果您没有对该程序集的引用(为什么不呢?)然后.ConfigureIf以某种方式使用和匹配类型(可能按名称)

于 2013-08-24T22:54:04.753 回答
1

我在这种情况下的旧方法是在 web.config 或专用 xml 文件中注册声明符。从 3.1 版开始,您可以为给定接口指定默认组件:使用命名约定策略将装饰器设置为默认组件变得非常容易,无论具体注册如何。

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

对不起,如果我不提供任何代码示例......但我现在正在度假

于 2013-08-23T18:10:43.080 回答