NotifyIcon
とその動的に入力された のみで構成される UI を使用して、WinForms アプリケーションを構築していContextMenuStrip
ます。MainForm
アプリケーションをまとめるための がありますが、それは決して目に見えません。
私はこれを可能な限りしっかりと構築することに着手し (Autofac を使用してオブジェクト グラフを処理します)、私の成功に非常に満足しています。現在実装している拡張機能では、設計に欠陥があり、少し改造する必要があるようです。必要な方法はわかっていると思いますが、依存関係を正確に定義する方法については少し不明です。
前述のように、アプリケーションの起動後に、メニューの一部が動的に読み込まれます。この目的のために、私はIToolStripPopulator
インターフェースを定義しました:
public interface IToolStripPopulator
{
System.Windows.Forms.ToolStrip PopulateToolStrip(System.Windows.Forms.ToolStrip toolstrip, EventHandler itemclick);
}
this の実装は に注入され、フォームで定義された および ハンドラを使用しMainForm
てLoad()
メソッドが呼び出されます。ポピュレータの依存関係は、メニュー項目に使用するデータの取得にのみ関連しています。PopulateToolStrip()
ContextMenuStrip
この抽象化は、いくつかの進化的なステップを経てうまく機能しましたが、複数のイベント ハンドラーが必要な場合には、もはや十分ではありません。たとえば、メニュー項目のいくつかの異なるグループを作成している場合などですIToolStripPopulator
。それにはまったく関心がありません。
私が言ったように、私は一般的な構造がどのようなものであるべきかを知っていると思います-IToolStripPopulator
インターフェースをより具体的なものに名前変更し*、メソッドがパラメーターをPopulateToolStrip()
取らない新しいものを作成しました。EventHandler
実装に必要なハンドラーの数に関する柔軟性の向上など)。このようにして、私の「最前線」IToolStripPopulator
は、任意の数の特定のもののアダプターになることが非常に簡単になります。
今、私がはっきりしていないのは、EventHandler の依存関係を解決する方法です。MainForm
メニューイベントに適切に反応するために必要な他のすべての依存関係があり、メニューも「所有」しているため、ハンドラはすべて で定義する必要があると思います。IToolStripPopulator
これは、最終的に MainForm に注入されるオブジェクトの依存関係が、MainForm
を使用してオブジェクト自体に依存する必要があることを意味しLazy<T>
ます。
私が最初に考えたのは、IClickHandlerSource
インターフェースを定義することでした:
public interface IClickHandlerSource
{
EventHandler GetClickHandler();
}
これは my によって実装され、MainForm
私の特定のIToolStripPopulator
実装は に依存していましたLazy<IClickHandlerSource>
。これは機能しますが、柔軟性に欠けます。ハンドラーの数が増える可能性があるため (MainForm
クラスで OCP に重大な違反)、個別のインターフェイスを定義するか、継続的に拡張するIClickHandlerSource
(主に ISP に違反する) 必要があります。イベント ハンドラーへの依存関係を直接取得することは、コンシューマー側にとっては良いアイデアのように見えますが、遅延インスタンス (など) のプロパティを介してコンストラクターを個別に接続するのは非常に面倒です (可能であれば)。
私の最善の策は現在これのようです:
public interface IEventHandlerSource
{
EventHandler Get(EventHandlerType type);
}
インターフェイスは引き続きMainForm
遅延シングルトンによって実装および注入され、EventHandlerType
必要なさまざまなタイプのカスタム列挙型になります。これはまだOCPに完全には準拠していませんが、適度に柔軟です。新しいイベント ハンドラー自体と (おそらく) 新しく作成された の追加実装に加えて、EventHandlerType
の解決ロジックと同様に、新しいタイプのイベント ハンドラーごとに変更があることは明らかです。MainForm
IToolStripPopulator
または....それを(唯一のオブジェクトとして)個別に実装するとIEventHandlerSource
、依存関係が発生し、オプションが?で定義された特定のハンドラーにLazy<MainForm>
解決されます。EventHandlerType
MainForm
私は実際にMainForm
実行可能な方法でイベント ハンドラーを取得する方法を考えようとしていますが、今のところうまくいくようには見えません。
ここで、さまざまなイベント ハンドラーの結合が最も緩く、最もエレガントな解決策を提供する最善の選択肢は何ですか?
[*はい、OCP に完全に準拠するために名前をそのままにしておくべきだったかもしれませんが、その方が見栄えがよくなりました。]