我正在设置一个asp.Net Mvc 4应用程序,并希望使用Onion Architecture模式进行配置 . 在过去,我使用了像这样的工作单元模式
public class UnitOfWork : IUnitOfWork, IDisposable
{
private IRepository<CallModel> _callRepo;
private IRepository<UserModel> _userRepo;
public IRepository<CallModel> CallRepo
{
get
{
if (_callRepo == null)
{
_callRepo = new Repository<CallModel>();
}
return _callRepo;
}
}
public IRepository<UserModel> UserRepo
{
get
{
if (_userRepo == null)
{
_userRepo = new Repository<UserModel>();
}
return _userRepo;
}
}
}
然后我会将UnitOfWork类的实例传递给Controller来做这样简单的CRUD .
public class QuestionsController : Controller
{
private IUnitOfWork _unitOfWork;
[Inject]
public QuestionsController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
我已将应用程序分成三个项目 .
-
核心
-
基础设施
-
网站
我的所有接口都在Core项目中,并在Infrastructure项目中实现了IRepository接口 . 如果我将UnitOfWork类放在Core项目中,那么因为它在Infrastructure项目中需要一个新的Repository,我正在创建一个从Core到Infrastructure的依赖项 . 如果我将它包含在基础设施中,那么Web项目(具有控制器)将依赖于基础设施,整个解决方案最终看起来不像洋葱,更像是意大利面 .
4 回答
嗯,不是真的 . 您的工作单元应该依赖于IRepository,而不是Repository实现本身 . 如果您正在使用依赖注入,这不应该成为问题,因为它应该找到正确的类型并在运行时提供它 . 我不确定Onion架构是否可以在不使用DI的情况下实现 .
请参阅david.s的答案,因为这正是我设置的方式 - 有一个项目的唯一目的是连接依赖项 .
我所做的是另一个名为
DependencyResolution
的项目,该项目引用了Core
和Infrastructure
,我在其中配置了IoC容器 . 然后我只能从Web
项目中反驳DependencyResolution
.我会喜欢david.s创建项目名为DependencyResolution,但让它重新启动Web,核心和基础设施 .
在那个项目中你可以做到:
并注册DI .
因此,不需要Web和基础架构之间的依赖 .
最好的祝福
对于它仍然值得的东西,我已经实现了我自己的库,它应用了UnitOfWork模式,与我之前在任何代码示例中看到的有点不同,但我发现它在实践中运行良好 . 简而言之:我有点复制.NET事务的工作方式,创建一个范围,然后在必要时在环境单元工作(-manager)中登记资源 . 基本上发生的是当处理新的消息/请求时,执行以下代码:
现在和事务一样,只要Thread仍然在范围内,就会出现一个环境UnitOfWork控制器,其中在请求期间使用和更改的所有资源都可以动态地登记 . 他们通过实现具有两种方法的IUnitOfWork接口来实现此目的:
然后,实现此接口的实例可以按如下方式登记:
通常,Repository-class将实现此接口,并且当它检测到它的托管聚合被更改/添加/删除时,它可以自我登记(双重登记被忽略) .
在我的例子中,框架假设您正在使用一个IOC框架,它将为您解析所有消息处理程序和存储库,因此我通过将当前IUnitOfWorkManager的实例注入到工作控制器的环境单元中来更容易地进行登记 . 必要时的构造函数 . 这样,工作单元管理器的依赖关系和需要刷新的实际部分(存储库,服务等)相反:
一旦成功处理了请求(没有抛出异常),就会调用scope.Complete(),触发控制器检查所有登记的项目是否(仍然)需要刷新(通过调用RequiresFlush()),如果是,则刷新它们(通过调用Flush()) .
总而言之,这允许一个非常可维护的解决方案(在我看来),其中可以动态添加新的存储库和其他依赖项,而无需更改任何主单元工作类,就像TransactionManager不需要预先知道哪些项目可能参与任何特定交易 .