Prism / Unityでこれが意味すること:Container.Resolve< ShellPresenter>()
-
10-07-2019 - |
質問
(Prism V2 StockTraderの StockTraderRIBootstrapper.cs ファイルからアプリの例)
これの違いは何ですか:
ShellPresenter presenter = new ShellPresenter();
そしてこれ:
ShellPresenter presenter = Container.Resolve<ShellPresenter>();
- 2番目の例は、コンテナーを工場のように扱い、「ShellPresenter型のインスタンス化されたオブジェクトが必要です」と言って、それまで歩いていくことを理解しています。
- しかし、例えばパラメーターを送信する必要があります。これは、「新しいShellPresenter(1、true)」に相当します。など?
- また、コンテナにはShellPresenterについて通知する必要があるため、プロジェクト内のどこかにShellPresenterクラスがコンテナに登録されている場所、たとえば、期待していた
次のようなもの:
Container.RegisterType<IShellPresenter, ShellPresenter>();
しかしどこにも見つからなかった。それでは、コンテナはこれらのタイプをどのようにして知ることができますか? これを独自のプロジェクトで再構築し、「依存関係の解決に失敗しました」を取得しました。エラー、この依存関係をどこに登録する必要がありますか?
ここでの指示/議論は役に立ちます。
原因不明の回答:
そのため、ブートストラップで、シェル自体を登録すると:
protected override void ConfigureContainer()
{
Container.RegisterType<IShellView, Shell>();
base.ConfigureContainer();
}
その後、コンテナはShellPresenterタイプを解決できます。 Shell タイプを登録すると、 ShellPresenter タイプはどのように登録されますか?
驚くべき答え:
わかりましたので、解決しようとしている型を登録する必要はありませんが、しようとしている型のコンストラクターに渡されるパラメーター(インターフェイス)型を登録する必要があります解決する、つまり、ShellPresenterのコンストラクタにIShellViewインターフェイスを挿入するため、IShellPresenter型ではなくIShellView型を登録する必要がありました。
public ShellPresenter(IShellView view) ...
テスターのタイプを解決して、これをテストしました:
Tester tester = Container.Resolve<Tester>();
コンストラクタに SomeClass を注入する限り:
public Tester(ISomeClass someClass)
コンテナに SomeClass を登録するまで、未解決の依存関係エラーが表示されます:
Container.RegisterType<ISomeClass, SomeClass>();
それで動作します。これは教育的であると同時に驚くべきことです。沈む必要があります。コーヒーを飲みに行き、しばらくこのことについて考えます。
これが事実である理由について詳しく説明できる人がいれば、大歓迎です。
解決
基本を理解しました。
コンストラクタの引数を必要とする型を解決するためのオーバーロードがあります。または、型をコーディングして、パラメータなしのコンストラクタを作成することもできます。
DIコンテナのポイントは、ソフトウェアを再コンパイルせずに、特定のインターフェイスで解決されるタイプを変更するようにコンテナを構成できることです。プロバイダーの構成用に提供したコード例は、実行時に変更できません。そのため、ほとんどの依存関係インジェクターでは、app.config / web.config /その他の外部構成ファイルでそれらを構成できます。そうすれば、再コンパイルせずに別のタイプを挿入するようにアプリを再構成できます。これはUnityのようなDIフレームワークの真の力です。
他のヒント
具象クラスを解決しようとして、それを満たすためにインスタンスまたはサブクラスを登録していない場合、Unityは具象クラスのインスタンスを作成して、依存関係を解決します。
したがって、ShellPresenterを要求して登録していない場合、UnityはShellViewをパラメーターとしてShellPresenterを新規作成します。
まあ、Untiyについては答えられませんが、Castle Windsorについては、app.config / web.configファイルに登録することができます。 config xmlにパラメーターを追加する機能もあります。
これにより、アプリケーションを再コンパイルすることなく、オブジェクトの実装と構成を変更できます。
Unityには、実行時に型を登録する Container.RegisterType&lt; TFrom、TTo&gt;()
メソッドセットがあります。おそらくXML構成ファイルを使用して行う方が一般的ですが、どちらでも機能します。
興味深いことに、Unityには Container.Resolve&lt; T&gt;(params object [] parameters)
-typeメソッドはありません。特定のコンストラクターパラメーター値で型を解決します。 Unityは、オブジェクトの構築とワイヤリングを行うためのP&amp; PチームのライブラリであるObjectBuilderの上に構築されています(IIRCはもともとObjectSpaces向けに作成されましたが、現在大幅に機能強化されています)。 ObjectBuilderには、コンストラクターを介するなど、さまざまな方法で依存関係を注入する機能があります。たとえば、依存型の新しいインスタンスを解決済み型のコンストラクターに渡すことができます。ただし、そのタイプも登録する必要があります。また、登録済みタイプのインスタンス(登録済みインスタンス/シングルトンなど)を渡すこともできます。しかし、AFAICSには単に渡す値を与える方法はありません。
それを行うと、IoCの哲学にある程度反することになると思うので、その機能を提供していないのです。コンテナは、理論上、どのような状況でも完全なオブジェクトグラフを提供できるはずです。したがって、パラメータを渡す必要はなく、オブジェクトは、注入可能なオブジェクト依存関係(コンテナが解決する)以外のコンストラクタパラメータに依存する必要はありませんあなたのために)悪いデザインとして見られています。
Windsor、StructureMap、またはその他を代弁することはできません。 Unityにはかなり慣れていないので、Unityがそれを行う方法がないと断言することさえできませんが、基本的にUnityを構築したIIRC Chris Tavaresは時々ここにたむろしているので、これに答えてください:-)