問題タブ [simple-injector]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - 登録コンテキスト (別名 Func) を使用して RegisterAll を実行する機能はどこにありますか)?
instanceCreator コンテキスト (aka ) を使用して単一の登録項目を登録できますFunc<T>
が、RegisterAll では同じ許可が得られないようです。
TL;DR - 受け入れられた回答を見つけて、更新 2 を確認してください (または、この質問の更新 3 までスキップしてください)。
これは私がやりたいことです:
以前の Stack Overflow answer for multiple registrationsに基づいて拡張機能を追加しようとしましたが、最後のものが勝つようです:
そもそもなぜ存在する必要があるのか にも興味がありRegisterAll
ます。これは、私が使用した 5 つの依存性注入コンテナーのうち、違いを生む最初の依存性注入コンテナーです。Resolve<IEnumerable<TService>>
他のものは、サービスに対して複数のタイプを登録し、 (autofac) またはGetAllInstances<TService>
(SimpleInjector と Ninject の両方)を呼び出してそれらをすべてロードすることを可能にします。
アップデート
より明確にするために、個々のアイテムを処理するコンポジットに渡すことができるアイテムのリストを作成しようとしています。スケジュール、トリガー、およびイベント (Rx) に基づいて実行されるようにすべて登録されるタスクのグループに分類されるため、上記と同じ問題が発生します。レジスタをすべて削除して、他のものをいくつか取り除くには:
以前に登録されたファイル ウォッチャーのすべてのインスタンスを取得していることがわかります。
私が知る必要があるのは、この問題の簡単な回避策と、いつ実装されるか (実装されない場合は、実装されない理由) です。また、Simple Injector の設計の現在の制限を考慮すると、これが不可能であることも認めます。私が受け入れられないのは、ツールの制限を満たすためにアーキテクチャを変更および適応させる必要があるということです。
更新 2
OCP (Open Closed Principle、別名 SOLID の O) について話しましょう。また、SimpleInjector がこの特定の原則を場合によって破る方法について私が感じている印象について話しましょう。
Open Closed Principle とは、拡張に対してオープンであり、変更に対してクローズであるということです。これが意味することは、ソース コードを変更せずにエンティティの動作を変更できるということです。
ここで、ここに関連する例に移りましょう。
それがどれほどきれいであるかに注意してください。ただし、これを行うには、インターフェイスのすべてのインスタンスを登録できる必要があります。
右?したがって、ここでの教訓は、これは優れており、OCP に適合しているということです。登録されているアイテムを追加または削除するだけで、タスク ランナーの動作を変更できます。拡張用に開き、変更用に閉じています。
次に、以下の回答で提案されている方法に焦点を当ててみましょう (最終的にこの質問に回答する 2 回目の更新の前)。これは、著者がより良いデザインであるという印象を与えています。
メンテナからの回答が言及している登録の優れた設計から始めましょう。私が得ている視点は、SimpleInjector で動作するように ITask をより柔軟にするために、コードを犠牲にしなければならないということです。
それでは、それによってデザインがどのように変化するかを見てみましょう。
ああ。コンテナー登録にアイテムを追加または削除するたびに、コードの別のセクションも更新する必要があることがわかります。1 回の変更で 2 か所の変更、複数の設計上の問題を解決しています。
なぜコンテナにこれを要求しているのかと言うかもしれません。これはスタートアップ領域にありますが、そうでない場合は調べてみましょう。
したがって、コンストラクター注入を使用して、これがなぜ悪いのかを説明します。まず、私の例をコンストラクション インジェクションとして見てみましょう。
素敵できれい。
さて、受け入れられた回答の見解についての私の理解に戻りましょう(更新2の前に):
ああ。コードの複数の領域を編集しなければならないたびに、この設計がどれほど貧弱であるかについては始めません。
ここでの教訓は何ですか?私は世界で最も賢い男ではありません。私は複数のフレームワークを維持しています (または維持しようとしています :))、他の人よりも多くのことを知っているふりをしたり、他の人よりもよく知っているふりをしたりしません。私のデザイン感覚がゆがんでいるのかもしれませんし、私がまだ考えもしていない未知の方法で他の人を制限しているのかもしれません. 著者がデザインに関するアドバイスをするのは善意であると確信していますが、場合によっては、特に私たちが何をしているのかを知っている私たちにとっては、迷惑な (そして少し見下すような) ものに遭遇するかもしれません.
アップデート 3
そのため、質問はメンテナーからの更新 2 で回答されました。私は RegisterAll を使用しようとしていました。これは、私が使用できるとは思いもよらなかったためですRegister<IEnumerable<T>>
(残念ながら、ドキュメントではこれが指摘されていませんでした)。今では完全に当たり前のように思えますが、他の IoC フレームワークから移行しようとしている人は荷物を抱えており、この驚くべきデザインの簡素化を見逃す可能性があります。他に 4 つの DI コンテナーを持っていたので、見逃してしまいました。うまくいけば、彼はそれをドキュメントに追加するか、もう少しうまく呼び出すでしょう.
c# - 依存性注入を使用して、複数のソースから構成を取得する方法は?
私はSimple Injectorを使用していますが、おそらく私が必要としているのは概念的な答えです。
アプリケーション設定とのインターフェースがあるとします。
次に、通常、IApplicationSettings を実装するクラスを持ち、指定されたソースから各フィールドを取得します。たとえば、次のようになります。
でも!EnableLogging
app.config、CopyLocal
データベース、およびServerName
現在のコンピューター名を取得する別の実装から取得したいとします。組み合わせごとに 1 つずつ、9 つの実装を作成することなく、アプリの構成をミックスマッチできるようにしたいと考えています。
インターフェイスはインジェクター (コンテナー) によって解決されるため、パラメーターを渡すことができないと想定しています。
私は最初にこれを考えました:
TEnableLogging
ただし、これには主な問題が 1 つあります。 ( である)のインスタンスを作成する方法を知るにはどうすればよいIGetValue<bool>
ですか? IGetValue<bool>
ああ、具象クラスによって実装される Value プロパティを持つインターフェースであると仮定します。ただし、具体的なクラスには、いくつかの詳細 (app.config のキーの名前など) が必要な場合とそうでない場合があります (単に常に true を返したい場合があります)。
私は依存性注入に比較的慣れていないので、間違った方法で考えているかもしれません。これを達成する方法について誰かアイデアがありますか?
(別の DI ライブラリを使用して答えることができますが、気にしません。その概念をつかむ必要があると思います。)
c# - DI を使用してコンテキストを持つプラグイン インスタンスを作成する
私はアプリケーションをリファクタリングして依存性注入 (コンストラクター注入による) を含めるようにしていますが、トリッキーなコーナーケースに遭遇しました:
現在、インスタンス化されたときに(抽象基本クラス) インスタンスImageViewer
のアセンブリを検索し、リフレクションを使用してそれらをインスタンス化するオブジェクトがあります。ImageViewerPlugin
これは、ImageViewer
次のようなメソッド (すべての具体的なプラグイン タイプのループで呼び出される) を使用するコンストラクターで行われます。
ImageViewerPlugin クラスは、おおよそ次のようになります。
具体的な実装は、おおよそ次のようになります。
各ImageViewer
インスタンスには、独自のImageViewerPlugin
インスタンスのコレクションがあります。
アプリケーションが DI コンテナーとコンストラクター インジェクションを使用するようにリファクタリングされたので、これらのプラグインには、DI コンテナーによって解決する必要がある依存関係 (以前はグローバル静的クラスの使用によって隠されていました) があることがわかりましたが、私はService Locator (アンチパターン) を使用せずにそれを行う方法がわからない。
最も賢明な解決策は、DI を使用してこれらのプラグイン インスタンスを作成することです。これにより、追加のコンストラクター パラメーターを追加して、依存関係をコンストラクター インジェクションを介して注入することができます。viewer
しかし、それを行う場合、残りのパラメーター値を注入しながら特定のパラメーター値を渡すにはどうすればよいでしょうか?
ImageViewerPluginFactory
これを達成するのに役立つと思いましたが、各プラグインが異なるコンストラクター署名を持つ可能性が高いため、そのようなファクトリを実装する方法がわかりません。
このシナリオをどのように解決できますか? それとも、これに完全に間違った方法でアプローチしていますか?
c# - SimpleInjector - ジェネリック型の多くの実装を LifetimeScopeLifestyle に登録する方法は?
SO でこの質問に答えている間、ジェネリック型の多くの実装をLifetimeScopeLifestyle
SimpleInjector 内のインスタンスに登録するための最良の手法がわかりませんでした。
この形式の登録に推奨される方法は、次のようなものです。
LifetimeScopeLifestyle
しかし、これは のインスタンスを渡すことを許可しません。
以下は私が思いついたものですが、具体的にではなく、一般的なインターフェイスをチェックしているため、十分な回復力がないことはわかっていますIRepository<>
。誰でもこれを行う方法を教えてもらえますか?
c# - Membus と Simple Injector - インターフェイスによるコマンド ハンドラの自動配線
Simple Injector に接続しようとした Membus の IoC 機能を見てきました
アイデアは、すべてのタイプを自動的に に登録するというものですRegisterManyForOpenGeneric(typeof<CommandHandler<>),typeof<CommandHandler<>).Assembly)
。
通常は正当な理由で間違いなく、SimpleInjector は複数の登録を許可しませんが、コマンド処理のさまざまな側面/懸念をさまざまなハンドラーによって実装するためにこれを行いたいと考えています。
確かに、IEnumerable<object> IocAdapter.GetAllInstances(Type desiredType)
membus からのインターフェースはコレクションを想定しているため、複数のハンドラーを呼び出すことができます。
Membus を SimpleInjector IC と組み合わせる最善の方法は何でしょうか?
脚注
私は、慣習によってメンバスを接続する他の方法を見てきました:
しかし、IoC コンテナーを使用してライフタイム スコープを処理し、コマンド ハンドラーをインスタンス化して必要になる前に手動で接続することを避けたいと考えています。