我有两个存储库AlbumRepository
,接口IAlbumRepository
和CachedAlbumRepository
接口IAlbumRepository
,其构造函数接口IAlbumRepository
。我需要使用带有ICachedAlbumRepository
的Ninject CachedAlbumRepository
和带有AlbumRepository
的构造函数注入。
如何使用Ninject实现它?
与结构图相同的方法
x.For<IAlbumRepository>().Use<CachedAlbumRepository>()
.Ctor<IAlbumRepository>().Is<EfAlbumRepository>();
public class CachedAlbumRepository : IAlbumRepository
{
private readonly IAlbumRepository _albumRepository;
public CachedAlbumRepository(IAlbumRepository albumRepository)
{
_albumRepository = albumRepository;
}
private static readonly object CacheLockObject = new object();
public IEnumerable<Album> GetTopSellingAlbums(int count)
{
string cacheKey = "TopSellingAlbums-" + count;
var result = HttpRuntime.Cache[cacheKey] as List<Album>;
if (result == null)
{
lock (CacheLockObject)
{
result = HttpRuntime.Cache[cacheKey] as List<Album>;
if (result == null)
{
result = _albumRepository.GetTopSellingAlbums(count).ToList();
HttpRuntime.Cache.Insert(cacheKey, result, null,
DateTime.Now.AddSeconds(60), TimeSpan.Zero);
}
}
}
return result;
}
}
答案 0 :(得分:3)
您需要创建2个绑定 - 一个表示将CachedAlbumRepository
注入需要IAlbumRepository
的任何内容,另一个表示将正常AlbumRepository
注入CachedAlbumRepository
。这些绑定应该这样做:
Bind<IAlbumRepository>()
.To<CachedAlbumRepository>();
Bind<IAlbumRepository>()
.To<AlbumRepository>()
.WhenInjectedInto<CachedAlbumRepository>();
答案 1 :(得分:2)
我无法回答你的问题,但我有一些反馈意见。
您的应用程序设计错过了一个很好的机会。它错过了成为并保持可维护的机会。由于您定义了一个装饰器(CachedAlbumRepository
是decorator),您可能也会开始为其他存储库编写装饰器。我想你有IArtistRepository
,IRecordLabelRepository
等装扮师。
必须实施这些重复的存储库违反了DRY原则。但是,违反DRY实际上是由违反其他一些原则引起的。您的设计违反了一些SOLID原则,即:
GetTopSellingAlbums
方法)不是很有凝聚力。换句话说,你的存储库类会变得很大,会做得太多,开始难以阅读,难以测试,难以改变,难以维护。此问题的解决方案是将所有存储库隐藏在一个通用抽象背后:
public interface IRepository<TEntity>
{
void Save(TEntity entity);
TEntity Get(Guid id);
}
由于这是一个通用接口,因此它不会给你任何添加任何特定于实体的查询方法的空间,这很好。这很好,因为IRepository<T>
将是狭窄和稳定的。这使得向它添加装饰器变得非常容易(如果你还需要在这里添加装饰器)。
诀窍是阻止向此接口添加查询方法(并且不从此接口继承新接口),而是为系统中的每个查询提供自己的类。或者实际上是两个班级。一个具有数据定义的类,以及一个知道如何执行该查询的类。最后但并非最不重要的是,您可以隐藏查询的相同通用抽象背后的每个类(就像我们对存储库有一个通用抽象)。当你这样做时,你只需要定义一个可以应用于系统中任何查询子集的缓存装饰器。
您可以阅读detail about this design here。一开始这看起来有点抽象,但我向你保证,当你掌握这一点时,你无法回到原来的设计。