我现在有一些空闲时间,所以我试图让我的头绕过DI和IoC容器。我从没有理由的情况下选择了团结,除了我可以告诉我的主要框架之间没有太大的区别之外,我应该过于在意开始。随着事情变得越来越复杂,我意识到我可能需要改变,但现在我希望它会做。DI,IoC,Unity和Moq的类型注册和实施令人困惑
因此,我正在使用一个相对简单的数据访问方案,并已实现了以下接口和数据访问类。
public interface IEventRepository
{
IEnumerable<Event> GetAll();
}
public class EventRepository : IEventRepository
{
public IEnumerable<Event> GetAll()
{
// Data access code here
}
}
然后使用我可以做到以下几点。
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(IEventRepository), typeof(EventRepository));
var eventRepo = container.Resolve<IEventRepository>();
eventRepo.GetAll();
如果我需要6个月我的数据库提供商从我的理解,我创建一个新的实现IEventRepository的改变和更新的注册类型,这很好。
现在,这里是我困惑的地方。例如,如果我想实现一些缓存,我可以从适当的IEventRepository实现继承,并覆盖实现必要缓存的适当方法。然而,这样做会让测试缓存更难以正确使用通过DI传入的Moq实现,所以在DI的真正精神中,我认为创建IEventRepository的实现是有意义的,然后使用DI来请求IEventRepository的实际数据访问实现就像这样。
public class CachedEventRepository : IEventRepository
{
private readonly IEventRepository _eventRepo;
public CachedEventRepository(IEventRepository eventRepo)
{
if (eventRepo is CachedEventRepository)
throw new ArgumentException("Cannot pass a CachedEventRepository to a CachedEventRepository");
_eventRepo = eventRepo;
}
public IEnumerable<Event> GetAll()
{
// Appropriate caching code ultimately calling _eventRepo.GetAll() if needed
}
}
这是否有意义,或者我是否会谈论这一切都是错误的?你会建议什么?如果我正确地做到了这一点,我该如何解决以下情况,以便CachedEventRepository获取适当的IEventRepository数据访问实现?
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(IEventRepository), typeof(EventRepository));
container.RegisterType(typeof(IEventRepository), typeof(CachedEventRepository));
var eventRepo = container.Resolve<IEventRepository>();
eventRepo.GetAll();
非常感谢您的帮助。
编辑1 以下是起订量的测试,我希望我能完成,我不认为将有可能使用继承和需要DI。
var cacheProvider = new MemoryCaching();
var eventRepo = new Mock<IEventRepository>(MockBehavior.Strict);
eventRepo
.Setup(x => x.GetAll())
.Returns(() =>
{
return new Event[] {
new Event() { Id = 1},
new Event() { Id = 2}
};
});
var cachedEventRepo = new CachedEventRepository(
eventRepo.Object,
cacheProvider);
var data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
Assert.IsTrue(data.Count() > 0);
eventRepo.Verify(x => x.GetAll(), Times.Once());
// This set method should expire the cache so next time get all is requested it should
// load from the database again
cachedEventRepo.SomeSetMethod();
data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
Assert.IsTrue(data.Count() > 0);
eventRepo.Verify(x => x.GetAll(), Times.Exactly(2));
您不应该在eventRepo单元测试中测试缓存日志。它揭示了SOLID范式的单一职责理念。 – 2012-04-19 20:57:19
我正在分别测试缓存和eventRepo。我试图测试的是将两者结合在一起,例如确保设置的方法过期相应的缓存。 – Hawxby 2012-04-20 08:18:37
是的,是的,我明白了。我现在没有更多的想法。 – 2012-04-20 08:33:09