1

AlbumRepositoryインターフェイスと、コンストラクター インターフェイスを持つインターフェイスIAlbumRepositoryの2CachedAlbumRepositoryつのリポジトリがあります。Ninject とコンストラクターで注入する必要があります。IAlbumRepositoryIAlbumRepositoryICachedAlbumRepositoryCachedAlbumRepositoryAlbumRepository

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;
        }
    }
4

2 に答える 2

2

質問にお答えすることはできませんが、いくつかフィードバックがあります。

あなたのアプリケーション設計は絶好のチャンスを逃しています。保守可能であり続ける機会を逃しています。デコレーターを定義したので (これCachedAlbumRepositorydecoratorです)、おそらく他のリポジトリー用のデコレーターも書き始めるでしょう。IArtistRepositoryIRecordLabelRepositoryなどのデコレータがあると思います。

これらの重複したリポジトリを実装しなければならないことは、DRY原則に違反しています。しかし、DRY の違反は、実際には他の原則の違反によって引き起こされます。あなたのデザインはSOLID原則のいくつかに違反しています。

  1. リポジトリ内に配置するクエリ メソッド (メソッドなど) があまりまとまっていないため、設計は単一責任の原則に違反しています。GetTopSellingAlbums言い換えると、リポジトリ クラスが大きくなりすぎて、読みにくくなり、テストしにくくなり、変更しにくくなり、維持しにくくなります。
  2. システムに新しいクエリを追加するたびにリポジトリを変更する必要があるため、設計はオープン/クローズの原則に違反しています。これは、インターフェースの変更、デコレーターの変更、実際の実装の変更、およびシステム内に存在するすべての偽の実装の変更を意味します。
  3. 設計はInterface Segregation Principleに違反しています。これは、リポジトリ インターフェイスが広くなり (多くのメソッドが含まれる)、それらのインターフェイスのコンシューマーが使用しないメソッドに依存することを余儀なくされるためです。これにより、デコレーターの実装と偽のオブジェクトの作成がますます難しくなっています。

この問題の解決策は、すべてのリポジトリを 1 つの汎用抽象化の背後に隠すことです。

public interface IRepository<TEntity>
{
    void Save(TEntity entity);
    TEntity Get(Guid id);
}

これは汎用インターフェイスであるため、エンティティ固有のクエリ メソッドを追加する余地はありません。これは良いことです。IRepository<T>幅が狭く安定するので良いです。これにより、デコレーターを簡単に追加できます (ここでデコレーターを追加する必要がある場合)。

秘訣は、このインターフェイスにクエリ メソッドを追加しないようにする (そして、このインターフェイスから新しいインターフェイスを継承しない) ことですが、システム内の各クエリに独自のクラスを与えることです。または実際には、2 つのクラス。データの定義を持つ 1 つのクラスと、そのクエリの実行方法を知っている 1 つのクラス。最後になりましたが、クエリの同じ汎用抽象化の背後に各クラスを隠すことができます (リポジトリに対して 1 つの汎用抽象化があるのと同じように)。これを行う場合、システム内のクエリのサブセットに適用できる 1 つのキャッシュ デコレータを定義するだけで済みます。

このデザインの詳細については、こちらをご覧ください。これは最初は少し抽象化されているように見えるかもしれませんが、これに慣れると、古い設計に戻ることは決してないことを約束します。

于 2013-04-22T19:09:11.613 に答える