多个程序集中的IoC容器注册

3

我希望了解在一个解决方案的不同项目中,将对象注册到IoC容器的最佳实践。

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

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

我看到一种解决方案是,在每个项目中创建一个容器,并在其中注册与该特定项目相关的对象。

那么,这种情况下最佳实践是什么?

3个回答

2
每个可执行项目都应该有自己的容器,因为它们能够独立运行而不依赖其他可执行项目。库项目通常提供依赖项,这些依赖项在可执行项目中被使用,因此如果想要使用库中的依赖项而库本身没有容器,那么就由可执行项目负责在其容器中注册这些依赖项。
拥有多个容器可能会导致各种问题,例如,如果一个类被注册为单例(所有依赖项的使用者共享一个引用),那么拥有多个容器将导致创建多个类的实例(每个容器中一个)。
如果存在跨项目依赖,则可能会导致问题,因为容器无法解析在另一个容器中注册的依赖项。

1
通常,我创建一个项目,其中包含大部分共享资源,例如模型、库以及我在其他项目中使用的IoC配置。通过从该项目配置IoC容器,我避免了复制粘贴。这样,我可以保留在使用此配置的项目中覆盖配置的可能性。
最终目的是为了可维护性。如果您在所有项目中使用相同的依赖项,则每个项目都需要单独配置,这将非常麻烦。

0
我们这里有一个例子:一个由许多项目组成的Web解决方案:一个核心项目和许多其他引用核心的项目。它们最终都会在不同的文件夹中(或者如果您喜欢,在构建后复制到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);
    }

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接