Search code examples
c#.netinversion-of-controlcastle-windsorioc-container

Registration of IoC containers from several assemblies


I try to understand what is best practice for registration of the objects into ioc container from different projects of one solution.

I have a solution with 4 projects and I saw a solution to create installers in each of the projects and then in one place call somtehing like this:

_container = new WindsorContainer();
            var assemblyNames = new[] {"Dal", "Utils" };
            _container.Install(assemblyNames.Select(
                    x => (IWindsorInstaller)new AssemblyInstaller(Assembly.Load(x),
                        new InstallerFactory())).ToArray());

But also I saw a solution that in each project, there is a creation of container, and inside there is a registration of the objects that are relevant to this specific project.

My question is: what is the best practice for this situation?


Solution

  • We have an example here : A web solution which consists of many projects : One Core project and many other which reference the core. All of them end up in different folders (or copied after build to the core/bin if you like). At start time we load them dynamically and then load the IWindsorInstallers from them. We load dlls like that :

    public static void LoadMoules()
    {            
        string basePath = AppDomain.CurrentDomain.BaseDirectory;
        string binPath = Path.Combine(basePath, "bin");
        DirectoryInfo binFolder = new DirectoryInfo(binPath);
        IEnumerable<FileInfo> binFiles = binFolder.EnumerateFiles("*.dll", SearchOption.AllDirectories);
        Assembly[] domainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
        try
        {
            foreach (var binFile in binFiles)
            {
                AssemblyName assemblyName = AssemblyName.GetAssemblyName(binFile.FullName);
                if (domainAssemblies.All(x => x.FullName != assemblyName.FullName))
                {
                    Assembly.Load(assemblyName.FullName);
                    Debug.WriteLine($"Loading {assemblyName.FullName}");
                }
            }
        }
        catch (Exception exception)
        {
           DynamicModuleLoaderEventSource.Log.FailedToLoadAssembly(exception.Message + exception.StackTrace);
    
        }    }
    

    Then we get the registrations :

        try
        {
            foreach(Assembly moduleAssembly in installationModules)
            {
                // satellite proejct assemblies 
    
                Debug.WriteLine(moduleAssembly.FullName);
                ContainerRegisterEventSource.Log.InstallAssembly(moduleAssembly.FullName);
                container.Install(FromAssembly.Instance(moduleAssembly));
            }
    
            container.Install(FromAssembly.This()); // the core assembly
        }
        catch(Exception exception)
        {
            ContainerRegisterEventSource.Log.Exception(exception.Message + exception.StackTrace);
            Trace.WriteLine("SetupContainerForMigrations error : " + exception.Message + Environment.NewLine + exception.StackTrace);
        }
    

    Doing it this way you will end up with one container with all the dependencies.