典型的なIoCコンテナーの使用-データを引き渡す
-
06-07-2019 - |
質問
最近 IoC コンテナーを初めて使用しましたが、 mを使用するためのベストプラクティスに関する教育を受けていない。具体的には、C#.NETプロジェクトで Unity を使用しています。 Prism が付属していたため、使用を開始しました。
コンテナを使用して「トップレベル」を解決します。オブジェクト、およびコンテナに基づいて注入された正しいオブジェクトを取得します。ただし、子供と子供の子供を持つオブジェクトがある場合、ベストプラクティスを明確に見ることができず、IoCコンテナからのデータが必要ですが、その間ではありません。 IoCコンテナーの使用を通常どのように整理しますか?
最初は、トップレベルのコンテナから必要なデータを抽出してこのデータを渡すのではなく、必要な場所にコンテナを渡すと思います。しかし、注入されたインターフェイスに加えて他の特定のデータを取得するオブジェクトに到達すると、再び問題が発生します。オブジェクトを解決した後、プロパティまたはinitメソッドを介してこれらのデータを注入したくないです。
これで十分に明確になったと思いますが、架空の(そして少しバカな..)例を見てみましょう。
class Employee
{
private ICommands _commands;
priate List<Customer> _customers = new List<Customer>();
public Employee(ICommands commands)
{
_commands = commands;
}
public void AddCustomer(string customerName)
{
var customer = new Customer(customerName, _commands);
_customers.Add(customer);
}
}
class Customer
{
private string _name;
private ICommands _commands;
priate List<Case> _cases = new List<Case>();
public Customer(string, name, ICommands commands)
{
_name = name;
_commands = commands;
}
public void AddCase()
{
var case = new Case(_commands);
_cases.Add(case);
}
}
class Case {
private ICommands _commands;
public Customer(ICommands commands)
{
_commands = commands;
}
public void TriggerCommands()
{
_command.TriggerSomething();
}
}
したがって、この例はあまり意味がありませんが、本質は私がする必要があるものと同じです。 ViewModelクラスを介して行を渡すアプリケーションコマンドがいくつかあります。それらの一部は、何かを表示するためにコマンドをトリガーできる必要があるためです。また、いくつかのクラスに必要な共通ストレージなどもありますが、現在は中間クラスにパススルーして格納されます。コマンドのみでコマンドやコンテナを保存しても大したことではありませんが、通常のIoC使用の場合は代わりにIoCコンテナを渡し、これを使用してオブジェクトを解決しますか?また、顧客名などの特定のデータについてはどうですか?これをResolve()で渡すことはできないので、後でそれを注入する必要がありますか?
申し訳ありません-これは私がそれを作ることができたのと同じくらい短かったです。同じ長さの回答は必要ありません;-) ..ただ; IoCコンテナでこのようなことを行うベストプラクティスは何ですか?
解決
私はあなたの質問を理解しているかどうかよくわかりません。しかし、コンテナを渡す必要はまったくないと思います。コンテナのラッパークラスを作成する方がはるかに簡単です。例:
public class IoCContainer
{
private static ContainerType = null;
public static ContainerType Instance
{
get
{
if (_container == null)
{
string configFileName = ConfigurationManager.AppSettings[ConfigFileAppSettingName];
_container = new WindsorContainer(new XmlInterpreter(configFileName));
}
return _container;
}
}
}
ここで、コードのどこでもこれを呼び出します。
IoCContainer.Instance.Resolve<IAwesomeService>();
これは役立ちますか?
他のヒント
これがあなたの質問に答えるかどうかはわかりませんが、Unityコンテナー(他のIoCエンジンにも適用可能)を使用してアプリケーションを操作する良い方法は次のとおりです:
- クラスを設計して、すべての 必要な依存関係が指定されています コンストラクター内。このように 明示的に対処する必要はありません 新しいものを作成する必要がない限り、Unity オブジェクト。
- 新しいオブジェクトを作成する必要がある場合
クラス内でUnityを渡します
コンストラクター内のコンテナー自体
同様に(への参照として
IUnityContainer
)、およびすべて新規作成Resolve
を使用してオブジェクトインスタンス 方法。そうでないオブジェクトでも 登録済みで依存関係がない、 コンテナは適切なものを提供します インスタンス、および後で、クライアントコードを変更せずに、以前に登録されていないタイプを登録することを決定できます。 - 明示的な値を解決済みオブジェクトに渡す場合、型を登録するときに具体的な注入メンバーを指定できます(
RegisterType
クラスのInjectionMembers
パラメーターを参照)。
エンティティのファクトリを宣言する必要があるようです。コンストラクター注入を介してファクトリーを解決し、Createメソッドを介してデータ値を渡します。他のすべての依存関係は、ファクトリのコンストラクタを介して解決する必要があります。
を参照これの答え。
特定のコンテナで初期化できる静的クラスIoCを定義し、Resolve、Resolve(...)などのメソッドを実装して、実際の作業をコンテナインスタンスに委任します(これを保存します)フィールドまたはプロパティのインスタンス)。この方法では、何も渡す必要はありません。使用するだけです
IoC.Resolve<SomeType>();
コードの任意の場所。
特定のデータに関して:一部のコンテナーはパラメーターを取得し、このパラメーターに応じて解決します(Autofacにはこの種の機能があります)。または、パラメータのセット(顧客名など)を受け入れ、対応するオブジェクトインスタンスを返すメソッドを持つファクトリクラスをいつでも作成できます。