Castle Windsor Configuration: Set Order for FromAssembly.InDirectory for Decorators

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

Answers


My old approach for this scenario was to register declarators within web.config or dedicated xml file. Since version 3.1 you can specify a Default component for a given interface: using a naming convention strategy became pretty easy to set decorators as default component, no matter the concrete registrations.

An other approach I use to ensure registration order, not just for decorators, is creating an InstallerFactory so you can easily drive installers execution order.

Sorry if I do not provide any code example... But I'm in vacation right now


use IsDefault for the decorator

doco

If you don't have a reference to that assembly (why not?) then use .ConfigureIf and match the type somehow (probably by name)


Need Your Help

Java Buttons not working

java swing mouseevent jbutton japplet

so in my program by buttons aren't working. I have it where if they're pressed they change a few variables which in turn change the label of a text. As near as i can tell the variables won't add wh...

Ruby on Rails with Plupload

ruby-on-rails ajax file-upload

I am looking for an upload solution for Ruby on Rails where I can upload multiple large image files simultaneously and show the progress to the uploader so they know the files are being uploaded. I

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.