サードパーティのツールなしでDIを実行することは可能ですか?DIフレームワークを発見する前に、抽象クラスとインターフェースを使用してそれを行っている人々について読んだことがあります。IDはその非常に基本的な形式でどのように行われますか?
5 に答える
インスタンス化するときに、依存関係をクラスのコンストラクターに渡すだけです。プロジェクトが小さい場合(数千行未満のコード)、DIフレームワークは必要ありません。ファクトリを作成し、すべての依存関係を手動で接続できます。
このチュートリアルには素晴らしい説明があります。
基本的には、DependingClass
についてのみ通知し、Interface
そのインターフェイスをで実装しますIndependentClass
。コンストラクターのオーバーロードを使用すると、たとえば、単体テストフレームワークにモックオブジェクトを送信させることができます。
いくつかのコードは、私が何をしているのかを理解しやすくするかもしれません:
public interface IAnInterface
{
void MethodOne();
void MethodTwo();
}
public class IndependentClass : IAnInterface
{
// Implements all members of IAnInterface
}
public class DependentClass
{
private IAnInterface _dependency;
public DependentClass() : this(new IndependentClass()) { }
public DependentClass(IAnInterface dependency)
{
this._dependency = dependency;
}
}
ご覧のとおり、コンストラクターに引数が指定されていない場合にインスタンス化されるデフォルトのクラスタイプが提供されています。ただし、同じインターフェイスを実装する別のクラス、または同じモックオブジェクトのインジェクションも許可しています。
編集:コメントで指摘されているように、より大きなアプリでは、をインスタンス化するファクトリを持ちDependingClass
、「デフォルト」コンストラクターを削除する方がおそらく良いでしょう。そうすれば、実装を変更することにした場合に、1か所で変更するだけで済みます。
もちろん、サードパーティのツールがなくても可能です。簡単なサンプル:
interface ILogger
{
void Log(string text);
}
class SomeClass
{
private ILogger _logger;
public SomeClass(ILogger logger)
{
_logger = logger;
}
public void DoSomeWork()
{
Log("Starting");
// do work
Log("Done");
}
private void Log(string text)
{
if (_logger != null)
{
_logger.Log(text);
}
}
}
SomeClass
ILogger
コンストラクターの入力としてを受け取ります。一部の出力をログに記録するために使用します。コンソールにそれが欲しいとしましょう:
class ConsoleLogger : ILogger
{
public void Log(string text)
{
Console.WriteLine(text);
}
}
いくつかのコードでは:
SomeClass instance = new SomeClass(new ConsoleLogger());
instance.DoSomeWork();
..しかし、代わりにファイルにログを記録する必要があります。
class FileLogger : ILogger
{
private string _fileName;
public FileLogger(string fileName)
{
_fileName = fileName;
}
public void Log(string text)
{
File.AppendAllText(_fileName, text);
}
}
したがって、代わりにファイルロガーを挿入します。
SomeClass instance = new SomeClass(new FileLogger("path to file"));
instance.DoSomeWork();
SomeClass
は、使用中の実装を喜んで認識せず、ILogger
注入された実装を使用するだけです。使用中の実装を簡単に変更できるようにするために、コード全体でオブジェクトを構築するのではなく、インターフェイス実装のインスタンスをファクトリで作成することをお勧めします。
インターフェイスを介して相互に通信するコンポーネントを作成し、コンポーネントをインスタンス化して相互にリンクするホスティングプログラムを作成できます。
これがソリューション構造になります。
コンポーネント間のコントラクトを定義するdllアセンブリ(インターフェイス+インターフェイスメソッドシグネチャの一部であるデータオブジェクト)。
コンポーネント(インターフェースを実装する)を定義するもう1つのdllアセンブリ。コンポーネント間の通信はすべて、インターフェースを介して行われます。
ホスティングプロセスを開始し、コンポーネントをインスタンス化し、いくつかのプロパティを設定してそれらをリンクするexeアセンブリ。1つのコンポーネントを置き換える必要があるときはいつでも、このプロジェクトを変更するだけで済みます。
テストしているコンポーネントによって使用されているコンポーネントをモックアップする任意のコンポーネントの単体テストを作成できます。
また、ホスティングプロジェクトのapp.confingファイルからプロパティバインディングを読みやすくすることもできます。
あなたがそれをすることができる3つの方法があります...
コンストラクターで依存インスタンス(もちろん、インターフェースを実装するクラスのインスタンス)への参照を渡します。
public class MyClass { private readonly ISpillDAL iSpDal; public ISpillDAL SpillDal { get { return iSpDal; } } public SpillLogic() : this(null) { } public SpillLogic(ISpillDAL splDAL) { iSpDal = splDAL ?? new SpillDAL(); // this allows a default } }
新しいオブジェクトを作成し、プロパティセッターを介して依存オブジェクトへの参照を渡します
public class MyClass { private readonly ISpillDAL iSpDal; public ISpillDAL SpillDal { set { iSpDal = value; } get { return iSpDal; } } public SpillLogic() { } }
参照を受け入れ、このために作成した内部provbate変数にそれを割り当てるオブジェクト内の関数を使用します
public class MyClass { private readonly ISpillDAL iSpDal; public ISpillDAL SpillDal { set { iSpDal = value; } get { return iSpDal; } } public SpillLogic() { } public void InjectSpillDAL( ISpillDAL splDAL ) { iSpDal = splDAL; } }