現時点では空き時間があるので、DI および IoC コンテナーについて頭を悩ませようとしています。私が unity を選んだ理由は、主要なフレームワーク間に大きな違いがなく、最初から心配しなければならないということ以外にはありません。後で物事がより複雑になると、変更が必要になる可能性があることに気付きますが、今のところはそれでうまくいくことを願っています.
したがって、私は比較的単純なデータ アクセス シナリオで作業しており、次のインターフェイスとデータ アクセス クラスを実装しています。
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 以下は、私が実行できることを望んでいた Moq テストです。継承を使用して実行することはできず、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));