从多个程序集注册IoC容器

时间:2017-06-26 08:26:14

标签: c# .net inversion-of-control castle-windsor ioc-container

我尝试了解从一个解决方案的不同项目将对象注册到ioc容器的最佳实践。

我有一个包含4个项目的解决方案,我看到了在每个项目中创建安装程序的解决方案,然后在一个地方调用这样的somtehing:

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

但我也看到了一个解决方案,在每个项目中,都有一个容器的创建,并且内部有一个与这个特定项目相关的对象的注册。

我的问题是:这种情况的最佳做法是什么?

3 个答案:

答案 0 :(得分:2)

每个可执行项目都应该有一个自己的容器,因为它们能够独立于其他可执行项目运行。库项目通常提供可执行项目中使用的依赖项,因此可执行项目负责在容器中注册这些依赖项,如果它想要在没有自己的容器的库中使用它们

拥有多个容器可能会导致各种问题,例如,如果一个类被注册为一个单例(在依赖项的所有使用者之间共享一个引用),那么具有多个容器将导致创建该类的多个实例(一个在每个容器)

如果存在跨项目依赖项,也可能导致问题,因为容器无法解析在另一个容器中注册的依赖项。

答案 1 :(得分:1)

通常我创建一个包含大部分共享资源的项目,例如我在其他项目中使用的模型,库和IoC配置。通过从这个项目配置IoC容器,我节省了一些复制粘贴。有了这个,我就可以覆盖您使用此配置的项目中的配置。

最后,它是关于可维护性的。如果您在所有项目中使用相同的依赖项,那么为每个项目一次又一次地配置它会很麻烦。

答案 2 :(得分:0)

我们在这里有一个例子:一个由许多项目组成的Web解决方案:One Core项目和许多其他引用核心的项目。所有这些文件最终都在不同的文件夹中(如果你愿意,可以在构建到core / bin之后复制)。在开始时我们动态加载它们,然后从它们加载IWindsorInstallers。我们加载这样的dll:

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

    }    }

然后我们得到注册:

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

这样做,最终会得到一个包含所有依赖项的容器。