NotifyIcon
とその動的に配置されたContextMenuStrip
で構成されるUIでWinFormsアプリケーションを構築しています。アプリケーションをまとめて保持するためのMainForm
がありますが、これは決して見えません。IoC:イベントハンドラへの依存関係の配線
私はこれをできるだけ完全に(オブジェクトグラフを扱うためにAutofacを使用して)構築することに着手しました。そして、私の成功に大変満足しています。私が現在実装している拡張機能では、私のデザインに欠陥があり、少し改造する必要があるようです。私は私が行く必要がある方法を知っていると思いますが、依存関係を正確に定義する方法については少し不明です。
前述のとおり、メニューはアプリケーションの起動後に部分的に動的に取り込まれます。この目的のために、私はIToolStripPopulator
インターフェイスを定義:
public interface IToolStripPopulator
{
System.Windows.Forms.ToolStrip PopulateToolStrip(System.Windows.Forms.ToolStrip toolstrip, EventHandler itemclick);
}
これの実装は、MainForm
に注入され、そしてLoad()
方法は、ContextMenuStrip
と形で定義されたハンドラにPopulateToolStrip()
を呼び出します。ポピュレータの依存関係は、メニュー項目に使用するデータの取得にのみ関連しています。
この抽象化は、いくつかの進化的なステップでうまく機能しましたが、複数のイベントハンドラが必要な場合には、これ以上十分ではありません。私はいくつかの異なるメニュー項目のグループを作成しています.1つのIToolStripPopulator
インターフェースの後ろに隠れていても、フォームはそれにはまったく関わってはいけないからです。私はより具体的なものにIToolStripPopulator
インタフェース*に改名し、代わりに注入され、そのPopulateToolStrip()
方法EventHandler
パラメータをとらない新しいものを、作成した - 私が言ったように
は、私はのような一般的な構造がどうあるべきか知っていると思いますオブジェクト(実装などで必要とされるハンドラの数に関してはるかに柔軟性を持たせることも可能です)。このように私の "最前の" IToolStripPopulator
は非常に簡単に任意の数のアダプターになります。
ここで私が不明な点は、EventHandlerの依存関係を解決する方法です。私はハンドラがMainForm
で定義されるべきだと考えます。なぜなら、それはメニューイベントに適切に反応するために必要な他のすべての依存関係を持ち、メニューも "所有"しているからです。つまり、IToolStripPopulator
オブジェクトの依存関係が最終的にMainFormに注入されると、Lazy<T>
を使用してMainForm
オブジェクト自体に依存する必要があります。
public interface IClickHandlerSource
{
EventHandler GetClickHandler();
}
これは私のMainForm
によって実装されました、そして、私の具体的なIToolStripPopulator
実装はLazy<IClickHandlerSource>
への依存を取っ:
私が最初に考えたのはIClickHandlerSource
インタフェースを定義されました。これは機能しますが、柔軟性がありません。 (MainForm
クラスのOCPに深刻に違反する)ハンドラの数が増えるにつれて別のインターフェイスを定義するか、またはIClickHandlerSource
(主に違反しているISP)を継続的に拡張する必要があります。 イベントハンドラに直接依存することは、コンシューマ側の良いアイデアのように見えますが、遅延インスタンス(または同様のもの)のプロパティを使用してコンストラクタを個々に配線することは可能です。
私の最善の策は、現在、このように思わ:
public interface IEventHandlerSource
{
EventHandler Get(EventHandlerType type);
}
インタフェースはまだMainForm
によって実装され、怠惰なシングルトンとして注入されるだろう、とEventHandlerType
は私が必要とするさまざまな種類のカスタム列挙型になります。これは依然として非常にOCPに準拠しているわけではなく、合理的に柔軟性があります。 EventHandlerType
は、明らかに新しいイベントハンドラの種類と、新しいイベントハンドラ自体と(おそらく)新たに書かれた追加実装IToolStripPopulator
に加えて、解決ロジックがMainForm
にあるように、新しいイベントハンドラごとに変更を加えることになります。
あるいは...(唯一のオブジェクトとして)MainForm
で定義された特定のハンドラにEventHandlerType
オプションをLazy<MainForm>
依存を取り、解決IEventHandlerSource
の別の実装?
実際にイベントハンドラをMainForm
の外に出す方法を考えようとしていますが、現時点ではあまり見えません。
他のイベントハンドラの最も緩やかなカップリングと最もエレガントな解決策を提供して、私の最高のオプションは何ですか?
[*はい、私はおそらく本当にOCPに準拠するために、単独で名を残しているはずですが、それは、より良い、そのように見えた。]
私はあなたの質問を複数回読みを実装するが、私はいくつかの情報が欠けています。より多くのコードを表示できますか?たとえば、 'IEventHandlerSource'のコンシューマはどのように見えますか?' IEventHandlerSource'の実装はどのように見えますか?これはどのように登録されていますか? – Steven