6

私はwcfサービスを持っており、クライアントには次のものがあります:

var service = new ServiceReference1.CACSServiceClient()

実際のサービス コードは次のとおりです。

public CACSService() : this(new UserRepository(), new BusinessRepository()) { }

public CACSService(IUserRepository Repository, IBusinessRepository businessRepository)
{
     _IRepository = Repository;
     _IBusinessRepository = businessRepository;
}

したがって、これはすべて正常に機能しますが、すべてのリポジトリを同時に更新する方法は好きではありませUserRepositoryBusinessRepository。このコードに何かを渡す方法はありますか:
var service = new ServiceReference1.CACSServiceClient()
サービスを呼び出しているコードに基づいてどのリポジトリを新しくするか、またはエンティティ フレームワークのリポジトリを設計するときに必要なその他のアドバイスを伝える方法があります。ありがとう

4

4 に答える 4

16

純粋な DI の利点は、依存関係の有効期間について心配する必要がないことです。依存関係は、提供者 (DI コンテナー、または自分で作成したその他のコード) によって管理されるためです。

(余談ですが、現在のBastard Injectionコンストラクターを削除する必要があります。パラメーターのないコンストラクターを破棄し、依存関係を明示的にアドバタイズするコンストラクターを保持します。)

コンストラクターを次のように保ち、必要に応じて _IRepository と _IBusinessRepository を使用します。

public CACSService(IUserRepository Repository, IBusinessRepository businessRepository) 
{ 
    _IRepository = Repository; 
    _IBusinessRepository = businessRepository; 
} 

これらのリポジトリのいずれかが実行時に必要ではないことが心配な場合は、最初に考えていた実際のリポジトリの代わりに、たとえば IUserRepsository の遅延読み込み実装を挿入できます。

IUserRepository が次のようになっているとします。

public interface IUserRepository
{
    IUser SelectUser(int userId);
}

次のような遅延読み込みの実装を実装できるようになりました。

public class LazyUserRepository : IUserRepository
{
    private IUserRepository uRep;

    public IUser SelectUser(int userId)
    {
        if (this.uRep == null)
        {
            this.uRep = new UserRepository();
        }
        return this.uRep.SelectUser(userId);
    }
}

CACService を作成するときに、LazyUserRepository を挿入することでこれを行うことができます。これにより、実際の UserRepository は必要な場合にのみ初期化されるようになります。

このアプローチの優れた点は、必要になるまでこれを行う必要がないことです。多くの場合、これは実際には必要ないため、実際に必要になるまでそのような最適化を延期できると便利です。

ここここで、 Lazy Dependencies の手法について最初に説明しました。

于 2010-02-27T21:02:43.317 に答える
0

構築時にリポジトリをインスタンス化 (「新規作成」) する代わりに、プロパティでそれらを遅延読み込みできます。これにより、2 番目のコンストラクターを保持できますが、最初のコンストラクターは何もしません。

ユーザーは、必要に応じてこれらを割り当てることができます。

例えば:

public class CACSService
{
    public CACSService() {}

    public CACSService(IUserRepository Repository, IBusinessRepository businessRepository)
    {
        _IRepository = Repository;
        _IBusinessRepository = businessRepository;
    }

    private IUserRepository _IRepository;
    public IUserRepository Repository
    {
        get {
             if (this._IRepository == null)
                  this._IRepository = new UserRepository();
             return this._IRepository;
        }
    }

   // Add same for IBusinessRepository
}
于 2010-02-27T20:03:15.110 に答える
0

リポジトリにはオブジェクト レベルの状態がありますか? おそらくそうではないので、それらをシングルトンとして作成し、DI コンテナーにそれらを CACService に提供させます。

そうでなければ、実際に作成するのに費用がかかりますか? そうでない場合、リクエストごとに新しいものを作成することは、RPC およびデータベース操作と比較してごくわずかなコストしかかかりません。

Ninject依存性注入コンテナーを使用すると、CACService は次のようになります。他の DI コンテナーには、これを行うための同様に簡潔なメカニズムがあります。

public class CACSService
{
    public CACService
    {
        // need to do this since WCF creates us
        KernelContainer.Inject( this );
    }

    [Inject]
    public IUserRepository Repository
    { set; get; }

    [Inject]
    public IBusinessRepository BusinessRepository
    { set; get; }
}

アプリケーションの起動時に、これらの型について Ninject に通知します。

Bind<IUserRepository>().To<UserRepository>().InSingletonScope();
Bind<IBusinessRepository>().To<BusinessRepository>().InSingletonScope();
于 2010-02-27T20:29:41.327 に答える
0

序文: これは、依存関係の逆転に関する一般的なガイドです。作業を行うためにデフォルトのコンストラクターが必要な場合 (たとえば、リフレクションなどによって新しく作成された場合)、これをきれいに行うのは難しくなります。

アプリケーションを構成可能にしたい場合は、オブジェクト グラフの構築方法を変更できることを意味します。非常に簡単に言えば、何かの実装を変更したい場合 (たとえば、 のインスタンスが必要な場合もあれば、 のインスタンスが必要な場合もありますUserRepository) 、その実装を使用MemoryUserRepositoryする型(この場合) に newing を課すべきではありません。それをアップします。を使用するたびに、特定の実装にバインドされます。 Misko は、この点についていくつかの素晴らしい記事を書いていますCACServicenew

依存関係の逆転の原則は、多くの場合、「上からのパラメーター化」と呼ばれます。これは、各具象型が呼び出し元から (既にインスタンス化された) 依存関係を受け取るためです。

これを実践するには、オブジェクト作成コードをCACServiceのパラメーターなしのコンストラクターから移動し、代わりにファクトリに配置します。

次に、次のようなものに基づいて、異なる方法で接続することを選択できます。

  • 構成ファイルの読み取り
  • ファクトリに引数を渡す
  • 異なるタイプの工場の作成

型を 2 つのカテゴリ (何かを作成する型と何かを実行する型) に分けることは、強力な手法です。

たとえば、ファクトリ インターフェイスを使用してそれを行う比較的簡単な方法の 1 つを次に示します。必要に応じて適切なファクトリを作成し、そのCreateメソッドを呼び出すだけです。私たちは Dependency Injection コンテナー ( Autofac ) を使用してこの作業を行っていますが、ニーズに対してはやり過ぎかもしれません。

public interface ICACServiceFactory
{
    CACService Create();
}

// A factory responsible for creating a 'real' version
public class RemoteCACServiceFactory : ICACServiceFactory
{
    public CACService Create()
    {
         return new CACService(new UserRepository(), new BusinessRepository());
    }        
}

// Returns a service configuration for local runs & unit testing
public class LocalCACServiceFactory : ICACServiceFactory
{
    public CACService Create()
    {
         return new CACService(
               new MemoryUserRepository(), 
               new MemoryBusinessRepository());
    }     
}
于 2010-02-27T20:40:02.337 に答える