我们有一个非常庞大,复杂的企业应用程序,在IOC容器在.NET中广泛使用之前于2005年开始。我们希望改进IOC容器,作为迁移到基于RabbitMQ(和easynetq)的完整事件驱动架构的一部分。作为一家企业,我们同意这将为我们提供超越竞争对手的商业优势。
我觉得提供一些序言非常重要,因为实施策略很关键:
目前,所有依赖注入都是基于构造函数和手动滚动的:
public sealed class TestCommandHandler
{
private readonly IUnitOfWork _unitOfWork;
private readonly ITestCommandValidator _testCommandValidator;
public TestCommandHandler(IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
this._testCommandValidator = new ITestCommandValidator(unitOfWork);
}
public TestCommandHandler(IUnitOfWork unitOfWork, IValidator testCommandValidator)
{
this._unitOfWork = unitOfWork;
this._testCommandValidator = testCommandValidator;
}
}
工作单元包含对可以轻易模拟的存储库的访问:
public class UnitOfWork : IUnitOfWork, IDisposable
{
private IAccountRepository _accountRepository;
public IAccountRepository Account
{
get
{
if(this._accountRepository == null)
{
this._accountRepository = new AccountRepository(this);
}
return this._accountRepository;
}
set
{
this._accountRepository = value;
}
}
//Begin Tx, Commit Tx etc
}
目前,所有测试依赖项都是在调试模式下有条件地编译的。发布代码使用非条件代码,我们在其中创建具体的依赖项。 最大的对象依赖是UnitOfWork,它通常围绕每个业务事务创建并向下传递。如,
using(var unitOfWork = new UnitOfWork())
{
}
这通常包含在另一个也支持IDisposable的类中。我们还计划将AccountID传递给UnitOfWork,这样我们就可以使用mod函数轻松地对不同的数据库进行Shard。
为了转移到依赖框架,感觉我们需要首先对UnitOfWork进行排序,但我们需要一个小步骤。我真的在寻找有关如此大型应用程序实现这一目标的最佳方法的建议。我们计划在圣诞节期间进行第一阶段,我们有一个很好的冻结,并在所有绝望的分支机构合并为一个主线分支,以进行重大改变。
我们开放使用依赖注入框架。我们在StructureMap上玩过一些游戏。我们看到Ninject在Nuget上有很高的下载统计数据,但是在性能上读得很差。我们真的不希望进一步迁移到另一个依赖注入框架。所以我们愿意接受建议。这不是一场最好的宗教战争,更重要的是我们有一些东西需要迁移。最重要的要求是它能够流畅地配置以避免配置地狱。
我们在StructureMap术语中的其他问题是我们如何声明注册表。我们是否按照程序集声明注册表?围绕文件夹,大型应用程序中的类名的任何推荐命名标准?我粗略猜测将有大约1000个注册表。对于如此庞大的代码库的扫描策略的任何想法?我们应该关注吗?
感谢您准备好这一点,但背景很重要,因为它不是一个10分钟的工作。
休伯特
答案 0 :(得分:2)
将此作为答案发布,但没有正确解决您的问题,只是为了克服评论限制。
为了实现IoC,您在场景中有很多优势:
所以,我会根据你目前的情况指出几点建议。
如果性能至关重要,请注意使用Ninject。作为一个沉重的Ninject用户,我发现它的Fluent配置,模块和上下文绑定非常灵活和强大。但是所有这些功能都需要付出代价,而且与其他IoC容器相比,每次激活请求的性能要差得多。
无论选择何种框架,并且您开始介绍这些更改,您都不希望被绑定到容器。确保你抽象它,然后你就可以开启另一个。
您已经按配置拆分了“模块”。插入容器配置代码时,请确保将它们收集到模块中。不要为在一个地方配置的所有模块保留所有依赖项。 Ninject支持模块,但使用任何容器都很容易实现,特别是如果你抽象它们。不要对虚拟/实际实现使用相同的模块名称,而是根据您的配置加载一个或另一个模块。
根据“自动注册”或“按惯例”,您应该非常严格并注意标准,否则很容易搞砸。我强烈建议不要使用激进的前期自动注册查询,并将它们保持在最小和非常简单的情况下,例如“IAccountRepository” - > “AccountRepository”或“AccountRepositoryImpl”。甚至那些,您可以按模块拆分约定,以便您可以覆盖它们以用于测试目的。
在发布周期中正常进行小的更改,不要进行分支更改并将其保留在那里,直到您将它们集成为止。就像你说的,宝贝步骤。你已经有依赖注入,所以这将是无痛的。在团队中加强此策略以使用容器,并在实现或重新设计功能时进行小的更改。
这是我的2美分,希望它有所帮助。