从多个程序集中注册 IoC 容器
Registration of IoC containers from several assemblies
我试图了解将对象从一个解决方案的不同项目注册到 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());
但我也看到了一个解决方案,在每个项目中,都有一个容器的创建,里面有一个与这个特定项目相关的对象的注册。
我的问题是:这种情况的最佳做法是什么?
通常我会创建一个项目,其中包含我在其他项目中使用的大部分共享资源,例如模型、库和 IoC 配置。通过从这个项目配置 IoC 容器,我为自己节省了一些复制粘贴。这样一来,我就可以覆盖您正在使用此配置的项目中的配置。
归根结底,一切都与可维护性有关。如果您在所有项目中使用相同的依赖项,那么为每个单独的项目一次又一次地配置它会很痛苦。
每个可执行项目都应该有自己的容器,因为它们能够 运行 独立于其他可执行项目。库项目通常提供在可执行项目中使用的依赖项,因此,如果它想在没有自己的容器的库中使用它们,可执行项目有责任在其容器中注册这些依赖项。
拥有多个容器可能会导致各种问题,例如,如果 class 被注册为单例(一个引用在依赖项的所有消费者之间共享),拥有多个容器将导致多个实例class 正在创建(每个容器一个)
如果存在跨项目依赖项,也可能会导致问题,因为容器无法解析在另一个容器中注册的依赖项。
我们这里有一个示例:一个由许多项目组成的 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);
}
这样做你最终会得到一个包含所有依赖项的容器。
我试图了解将对象从一个解决方案的不同项目注册到 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());
但我也看到了一个解决方案,在每个项目中,都有一个容器的创建,里面有一个与这个特定项目相关的对象的注册。
我的问题是:这种情况的最佳做法是什么?
通常我会创建一个项目,其中包含我在其他项目中使用的大部分共享资源,例如模型、库和 IoC 配置。通过从这个项目配置 IoC 容器,我为自己节省了一些复制粘贴。这样一来,我就可以覆盖您正在使用此配置的项目中的配置。
归根结底,一切都与可维护性有关。如果您在所有项目中使用相同的依赖项,那么为每个单独的项目一次又一次地配置它会很痛苦。
每个可执行项目都应该有自己的容器,因为它们能够 运行 独立于其他可执行项目。库项目通常提供在可执行项目中使用的依赖项,因此,如果它想在没有自己的容器的库中使用它们,可执行项目有责任在其容器中注册这些依赖项。
拥有多个容器可能会导致各种问题,例如,如果 class 被注册为单例(一个引用在依赖项的所有消费者之间共享),拥有多个容器将导致多个实例class 正在创建(每个容器一个)
如果存在跨项目依赖项,也可能会导致问题,因为容器无法解析在另一个容器中注册的依赖项。
我们这里有一个示例:一个由许多项目组成的 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);
}
这样做你最终会得到一个包含所有依赖项的容器。