Pau*_*lor 24 asp.net-mvc entity-framework castle-windsor inversion-of-control
我使用Entity Framework数据库优先方法为MVC应用程序生成DbContext/POCO模型.我想避免在我的控制器中依赖DbContext来使我能够根据需要切换到另一个持久性提供程序(例如用于单元测试).
为此,我想使用Castle Windsor IoC容器.我计划将DbContext注册为IUnitOfWork服务并注册一个通用的IRepository服务,我将使用它来访问和使用模型中的聚合根.
我是Windsor的新手,并且无法找到关于在EF中使用它的更多信息,我有几个问题:
Pau*_*lor 25
所以,一些结论.我想我会写这个,以防其他人试图使用/单元测试EF,Windsor和MVC.
首先,由于DbContext同时实现了Repository和Unit of Work模式,因此您需要了解这些实现是否会提供服务,或者您是否需要创建自己的实现.
我选择按照DDD模式创建自己的Repository:每个聚合根一个.原因是:封装查询代码,防止它泄漏到应用程序层,并且在测试应用程序控制器时能够更容易地进行模拟.我创建了一个基于的通用存储库IRepository<TEntity>.那里有很多例子.我发现这是一个很好的:http://architects.dzone.com/articles/implementing-repository
另一方面,我决定放弃IUnitOfWork服务,而是选择默认实现.但是,我创建了一个IDbContext抽象(不知道微软为什么不自己这样做),所以我可以在测试Repository服务时模拟DbContext.
我只向IDbContext提供了我想在存储库中使用的DbContext的成员.所以:
public interface IDbContext: IDisposable
{
Database Database { get; }
DbEntityEntry Entry(object entity);
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
然后,我为我的IDbContext和IRepository服务创建了一个Windsor工具和安装程序:
public class EntityFrameworkFacility: AbstractFacility
{
protected override void Init()
{
Kernel.Register(Component.For<IDbContext>()
.ImplementedBy<MyEntities>()
.LifestylePerWebRequest(),
Component.For(typeof(IRepository<>))
.ImplementedBy(typeof(Repository<>))
.LifestylePerWebRequest());
}
}
public class PersistenceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<EntityFrameworkFacility>();
}
}
Run Code Online (Sandbox Code Playgroud)
最后一部分是扩展Entity Framework上下文类以实现IDbContext,并将Set()方法隐藏为返回IDbSet而不是DbSet:
public partial class MyEntities : IDbContext
{
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
}
Run Code Online (Sandbox Code Playgroud)
完成所有这些(以及Windsor文档中说明的ControllerFactory注册),让Windsor根据需要将IRepository对象(或IDbContext)注入控制器构造函数变得微不足道:
public ControllerBase(IRepository<Contact> repo)
{
_repo = repo;
}
Run Code Online (Sandbox Code Playgroud)
在Repository单元测试中,可以使用模拟IDbContext支持真实存储库实例:
mocks = new MockRepository();
context = mocks.StrictMock<IDbContext>();
repo = new Repository<Contact>(context);
Run Code Online (Sandbox Code Playgroud)
在Controller单元测试中,可以使用模拟存储库:
mocks = new MockRepository();
repo = mocks.StrictMock<IRepository<Contact>>();
ContactController controller = new ContactController(repo);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9262 次 |
| 最近记录: |