私は私たちが思いついたものだけを説明することができます。さまざまなオンラインライブラリからユーザビリティ構文などを借りてきましたが、コードはすべて私たちのものです。
基本的に、ServiceContainerと呼ばれるオブジェクトがあります。そのグローバルインスタンスが常に存在し、必要に応じてシングルトンコピーが静的に存在するため、Webアプリケーションでは、appdomain内のすべてのユーザー間で共有されます。
ServiceContainerにはルールが含まれています。ルールには、誰かがXYZタイプのオブジェクトを要求した場合、次のようにオブジェクトを提供する方法が示されています。
たとえば、一部のコードがIDbConnectionを実装するオブジェクトを取得するために、コンテナが新しいSqlConnectionオブジェクトを構築、構成、および返すというルールが考えられます。
したがって、問題のコードは、OleDbConnectionオブジェクトではなく、SqlConnectionオブジェクトを使用していることを認識せず、気にしません。
それを書いたので、これはあまり良い例ではないことに気付きました。最終的にはコマンドオブジェクトの接続を要求することになり、そのオブジェクトに与えるSQL構文は接続のタイプに合わせて調整する必要があるからです。しかし、その点を今すぐ無視できる場合、コードはSQL Serverに接続していることを認識せず、接続オブジェクトがあることを認識しているだけです。
ここで問題となっているコードには、使用するコンテナー、つまりルールを指定する必要があります。これは、単体テストの観点から、ServiceContainerの新しいインスタンスを作成し、テスト目的でそのインスタンスに新しいルールを記述し、コードにその処理を依頼できることを意味します。最終的に、コードは(この場合は)SQlを実行する必要があり、実際のデータベースと通信する代わりに、IDbConnectionとIDbCommandのテスト実装を呼び出して、動作を確認する機会を与えてくれます。
さらに重要なことに、データベース全体をモックアップすることなく、テストに適合する既知のダミーデータを返す方法が提供されます。
さて、インジェクション部分については、この場合、他のオブジェクトに依存する、構築する必要のあるオブジェクトをコンテナに提供するように依頼できます。
たとえば、IDataAccessLayerインターフェイスとMSSQLDataAccessLayer実装があるとします。
インターフェイスは、ログを記録するという外見上の兆候を示しませんが、ここでの実際の実装には、実行するすべてのSQLをログに記録する場所が必要です。したがって、クラスのコンストラクターは次のようになります。
public MSSQLDataAccessLayer(ILogger logger) { ... }
ServiceContainerオブジェクトに、次のルールを登録しました(これは構文であり、他の場所では見つかりませんが、従うのは簡単です)。
ServiceContainer.Global.RegisterFactory<ILogger, FileLogger>()
.FactoryScoped()
.WithParameters(
new Parameter("directory", @"C:\Temp")
);
ServiceContainer.Global.RegisterFactory<IDataAccessLayer, MSSQLDataAccessLayer>()
.FactoryScoped();
FactoryScopedは、コンテナにオブジェクトを要求するたびに、新しいオブジェクトを取得することを意味します。
私が英語で書いた場合のルールは次のとおりです。
- ILoggerの実装が必要な場合は、新しいFileLoggerオブジェクトを作成し、「directory」パラメーターを必要とするコンストラクターを取得して、引数として「C:\Temp」を渡すときにそのコンストラクターを使用します。
- IDataAccessLayerの実装が必要な場合は、新しいMSSQLDataAccessLayerを作成します
MSSQLDataAccessLayerのコンストラクターはILoggerを使用することを前に述べましたが、ここではパラメーターを指定していません。これにより、アクセスレイヤーオブジェクトを取得するための次のコードが得られます。
IDataAccessLayer dal = ServiceContainer.Global.Resolve<IDataAccessLayer>();
ここで何が起こるかというと、コンテナーオブジェクトは、オブジェクトがMSSQLDataAccessLayerであり、コンストラクターを持っていることを認識します。このコンストラクターにはILoggerオブジェクトが必要ですが、見よ、コンテナーはILoggerオブジェクトの作成方法を知っています。したがって、コンテナーは新しいFileLoggerオブジェクトを作成し、これをMSSQLDataAccessLayerオブジェクトのコンストラクターにサイレントに渡します。
したがって、アプリケーションの依存関係の多くの構成は、起動時に中央のどこかで実行できますが、残りのコードは、ここで発生するすべての魔法に気づいていません。
単体テストの目的で、ルールを書き直して、ログに記録されたテキストをメモリに保存するだけの独自のダミーロガーオブジェクトを提供できます。これにより、ログに記録する予定のコードが実際にログに記録されたことを簡単に確認できます。後でファイルします。
ルールは、オブジェクトインスタンスを実際に提供する方法について多くの力を与えてくれます。
- デリゲート/メソッドから。つまり、必要に応じて、依存オブジェクトを自分で構築するすべての魔法を実行できます。
- コンストラクターから自動的に(どちらを使用するかを自動的に判断するか、名前/タイプによって1つを選択するのに十分なダミーパラメーターを提供できます)
- または、既存のインスタンスをコンテナに提供することもできます(これにより、シングルトンのようになります)
autofacを調べてから独自のシステムを作成しました。基本的には、呼び出し構文の例を示すwikiを見てから、座って、必要なことを実行する独自のシステムを作成しました。