您认为使用 IOC 比不使用它需要更多的代码。我不同意。
这是我使用 LinqToSql 的一个项目的整个 DAL IOC 配置。 ContextProvider 类只是一个线程安全的 LinqToSql 上下文工厂。
container.Register(Component.For<IContextProvider<LSDataContext>, IContextProvider>().LifeStyle.PerWebRequest.ImplementedBy<ContextProvider<LSDataContext>>();
container.Register(Component.For<IContextProvider<WorkSheetDataContext>, IContextProvider>().LifeStyle.PerWebRequest.ImplementedBy<ContextProvider<WorkSheetDataContext>>();
container.Register(Component.For<IContextProvider<OffersReadContext>, IContextProvider>().LifeStyle.PerWebRequest.ImplementedBy<ContextProvider<OffersReadContext>>();
这是我使用 NHibernate 和存储库模式的一个项目的整个 DAL 配置:
container.Register(Component.For<NHSessionBuilder>().LifeStyle.Singleton);
container.Register(Component.For(typeof(IRepository<>)).ImplementedBy(typeof(NHRepositoryBase<>)));
这是我在 BLL 中使用 DAL 的方式(使用依赖注入):
public class ClientService
{
private readonly IRepository<Client> _Clients;
public ClientService(IRepository<Client> clients)
{
_Clients = clients;
}
public IEnumerable<Client> GetClientsWithGoodCredit()
{
return _Clients.Where(c => c.HasGoodCredit);
}
}
请注意,我的 IRepository 接口继承了 IQueryable 所以这段代码非常简单!
以下是在不连接数据库的情况下测试 BLL 的方法:
public void GetClientsWithGoodCredit_ReturnsClientWithGoodCredit()
{
var clientWithGoodCredit = new Client() {HasGoodCredit = true};
var clientWithBadCredit = new Client() {HasGoodCredit = false};
var clients = new List<Client>() { clientWithGoodCredit, clientWithBadCredit }.ToTestRepository();
var service = new ClientService(clients);
var clientsWithGoodCredit = service.GetClientsWithGoodCredit();
Assert(clientsWithGoodCredit.Count() == 1);
Assert(clientsWithGoodCredit.First() == clientWithGoodCredit);
}
ToTestRepository() 是一个扩展方法,它返回一个使用内存列表的假 IRepository。
您无法争辩说这比在您的 BLL 上更新 DAL 更复杂。
编写上述测试的唯一方法是连接到数据库,保存一些测试客户端,然后进行查询。我保证执行时间比这要长 100 倍以上。 (乘以 1000 次测试,您可以在等待时去喝杯咖啡。)
此外,通过使用未提交的事务进行测试,您会引入由不查询未提交实体的 ORM 导致的调试噩梦。