マーク・シーマンはそれを正しく理解しました。そして、私はあなたの混乱に同情します。自動依存性注入コンテナーの使用法を学んだとき、私は自分でそれを経験しました。問題は、オブジェクトを設計および使用する有効で妥当な方法が多数あることです。しかし、自動依存性注入コンテナーで機能するのは、これらのアプローチの一部のみです。
私の経歴: Unity や Castle Windsor コンテナーなどの Inversion of Control コンテナーの使用方法を学ぶずっと前に、オブジェクト構築のオブジェクト指向の原則と Inversion Of Control を学びました。次のようなコードを書く習慣を身につけました。
public class Foo
{
IService _service;
int _accountNumber;
public Foo(IService service, int accountNumber)
{
_service = service;
_accountNumber = accountNumber;
}
public void SaveAccount()
{
_service.Save(_accountNumber);
}
}
public class Program
{
public static void Main()
{
Foo foo = new Foo(new Service(),1234);
foo.Save();
}
}
この設計では、Foo クラスがアカウントをデータベースに保存する役割を果たします。それを行うには口座番号が必要であり、汚い仕事をするためのサービスが必要です。これは、各オブジェクトがコンストラクターでいくつかの一意の値を取る、上で提供した具象化されたクラスにいくぶん似ています。これは、独自のコードでオブジェクトをインスタンス化する場合にうまく機能します。適切なタイミングで適切な値を渡すことができます。
しかし、自動依存性注入コンテナーについて知ったとき、もはや手動で Foo をインスタンス化していないことに気付きました。コンテナーは、コンストラクターの引数をインスタンス化します。これは、IService のようなサービスにとって非常に便利でした。しかし、整数や文字列などではうまく機能しないことは明らかです。そのような場合、デフォルト値 (整数のゼロなど) が提供されます。代わりに、アカウント番号、名前などのコンテキスト固有の値を渡すことに慣れていました...そのため、コーディング スタイルとデザインを次のように調整する必要がありました。
public class Foo
{
IService _service;
public Foo(IService service)
{
_service = service;
}
public void SaveAccount(int accountNumber)
{
_service.Save(accountNumber);
}
}
public class Program
{
public static void Main()
{
Foo foo = new Foo(new Service());
foo.Save(1234);
}
}
両方の Foo クラスが有効な設計であるように見えます。ただし、2 番目は自動依存性注入で使用できますが、1 番目は使用できません。