How to force the order of Installer Execution
Asked Answered
S

3

8

I have been building a new .NET solu­tion with Cas­tle per­form­ing my DI.

Its now at the stage where i would like to con­trol the order in which my installers run. I have built indi­vid­ual classes which implement IWind­sorIn­staller to han­dle my core types — eg IRepos­i­tory, IMap­per and ISer­vice to name a few.

I see that its suggested i implement my own Installer­Fac­tory (guessing i just override Select) in this class.

Then use this new factory in my call to:

FromAssembly.InDirectory(new AssemblyFilter("bin loca­tion")); 

My ques­tion — when over­rid­ing the save method — what is the best way to force the order of my installers.

Stumper answered 15/6, 2011 at 13:14 Comment(2)
Add the installers manually in the order you need? Anyway, can you tell us why you need to define a specific order?Vocalist
well, lets just assume i want to guarantee that the Service installer runs first of all (the dependency graph permitting). The documentation says that overriding InstallerFactory is the way to go. There just seems to be very little covered on this topic. I think it ultimately comes down to re-ordering the IEnumerable<Type> that is passed in to the Select methodStumper
P
21

I know its already solved but I couldn't find any example on how to actually implement the InstallerFactory so here's a solution if anyone is googling for it.

How to use:

[InstallerPriority(0)]
    public class ImportantInstallerToRunFirst : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
        {
            // do registrations
        }
    }

Just add the InstallerPriority attribute with a priority to your "install-order-sensitive" classes. Installers will be sorted by ascending. Installers without priority will default to 100.

How to implement:

public class WindsorBootstrap : InstallerFactory
    {

        public override IEnumerable<Type> Select(IEnumerable<Type> installerTypes)
        {
            var retval =  installerTypes.OrderBy(x => this.GetPriority(x));
            return retval;
        }

        private int GetPriority(Type type)
        {
            var attribute = type.GetCustomAttributes(typeof(InstallerPriorityAttribute), false).FirstOrDefault() as InstallerPriorityAttribute;
            return attribute != null ? attribute.Priority : InstallerPriorityAttribute.DefaultPriority;
        }

    }


[AttributeUsage(AttributeTargets.Class)]
    public sealed class InstallerPriorityAttribute : Attribute
    {
        public const int DefaultPriority = 100;

        public int Priority { get; private set; }
        public InstallerPriorityAttribute(int priority)
        {
            this.Priority = priority;
        }
    }

When starting application, global.asax etc:

container.Install(FromAssembly.This(new WindsorBootstrap()));
Plowboy answered 25/8, 2011 at 15:44 Comment(2)
This is the kind of extension point that should definitely be merged into Windsor. Great job.Bachman
Interestingly this approach doesnt work if you are registering installers from different assemblies. The installer factory is called once per assembly.Salpinx
N
3

You can call your installers in the order they need to be instantiated in Global.asax.cs or e.g. in a Bootstrapper class, which is called from Global.asax.cs.

        IWindsorContainer container = new WindsorContainer()
            .Install(                    
                new LoggerInstaller()           // No dependencies
                , new PersistenceInstaller()    // --""--
                , new RepositoriesInstaller()   // Depends on Persistence
                , new ServicesInstaller()       // Depends on Repositories
                , new ControllersInstaller()    // Depends on Services
            );

They are instantiated in this order, and you can add a breakpoint after and check the container for "Potentially misconfigured components".

If there are any, check their Status->details, if not, it's the correct order.

This solution is quick and easy, the documentation mentions using a InstallerFactory Class for tighter control over your installers so if you have a ton of installers the other solution may fit better. (Using code as convention should not require tons of installers?)

http://docs.castleproject.org/Windsor.Installers.ashx#codeInstallerFactorycode_class_4

Noe answered 27/5, 2013 at 6:10 Comment(1)
this will indeed work, however in the solution which caused this question we had unknown installers within libraries referenced, and we wanted to guarantee they would all get picked based on our convention, but run in a specific order - again based on convention.Stumper
S
0

In the end i had to use InstallerFactory and implement the ordering rules as suggested previously by returning the IEnumerable<Type> with my specific order

Stumper answered 12/7, 2011 at 9:9 Comment(2)
Do you have link to some more info on the InstallerFactory?Rockey
@Chev i didn't find too much written about this, i simply had to use trial and error to get the result i was looking for.Stumper

© 2022 - 2024 — McMap. All rights reserved.