重複したイベント処理コードをリファクタリングする方法
-
27-09-2019 - |
質問
特定のオブジェクトを変更イベントに購読できる次のクラスがあります。問題は、私もクラスBと、オブジェクトが同じ種類のものにサブスクライブできるようにするこの機能を必要とするCもあることです。私たちは確かにこの動作をコピーして貼り付けたくありません。
私たちは共通の基本クラスから継承することを検討しましたが、A、B、Cを含むすべてのクラスはすでに一般的なベースクラスから継承しています。また、ベースクラスから継承する他のクラスe、f、gがこの動作を必要としないため、この動作をベースクラスに追加したくありません。
より良い解決策はありますか?
public class A : BaseClass
{
/*other properties and code */
public event EventHandler OnChange;
private bool _hasChanged;
public bool HasChanged
{
get { return _hasChanged; }
set
{
_hasChanged = value;
//only need to notify when we've changed.
if (value)
{
if (OnChange != null)
OnChange(this, EventArgs.Empty);
}
}
}
}
解決
継承を一瞬使用しない場合はどうなりますか?
1-共通の基本クラスから継承する代わりに、イベントメカニズムを実装するオブジェクトを使用してイベントメカニズムを必要とするクライアントクラスを作成するとします。
私たちのクラスがそうであると仮定します
public class EventNotifier
{
public event EventHandler OnChange;
private bool _hasChanged;
public bool HasChanged
{
get { return _hasChanged; }
set
{
_hasChanged = value;
//only need to notify when we've changed.
if (value)
{
if (OnChange != null)
OnChange(this, EventArgs.Empty);
}
}
}
}
2-
public class A
{
private EventNotifier eventNotifier;
public EventNotifier MyEventNotifier { get { return eventNotifier; } }
public A()
{
eventNotifier = new EventNotifier();
}
}
3-これで、クラスAのユーザー(継承されているクラス /クラスAのクラス)
これは、bがaを含む場合です
public class b
{
A obj ;
public b()
{
obj = new A();
obj.MyEventNotifier.OnChange += new EventHandler(delegate { Console.WriteLine("Hi"); });
obj. MyEventNotifier.HasChanged = true;
}
}
他のヒント
これで使用されているように、アスペクト指向のプログラミングアプローチを検討してください シャープ後の例. 。属性を使用してそのようなボイラープレートコードを注入することができます。
適切な側面を作成した場合、次のようなコードを作成できます。
public class A : BaseClass
{
public event EventHandler OnChanged;
[ChangedNotify("OnChanged")]
public bool HasChanged { get; set; }
}
または、アイデアがシングルを持つことである場合 OnChange
複数のプロパティのイベントでは、それをアスペクトにハードコードして、コードを減らすことができます
public class A : BaseClass
{
[NotifyOnChanged]
public bool HasChanged { get; set; }
}
共通の動作を含むA、B、Cの間に仲介クラスを導入することを検討できます。このようにして、動作を必要としないE、F、Gを汚染しません。
BaseClass
-----------------------------
| |
----- NotifyBaseClass
E,F,G |
-----
A,B,C
NB AOPは美味しそうに見えますが、MSコード分析やMSBuildなど、ポストシャープを他のテクノロジーと連携させようとする大きな問題がありました。
通知可能なオブジェクトのサブクラスを持つことは行く方法かもしれませんが、そのように幅広い異なるクラスに乗るのは難しい場合があります。別の方法では、ベースクラスにそれを含めて、インターフェイスを定義してから、関連するクラスのインターフェイスをタックするだけです。
実行するときは、それが快適な(または何か)かどうかを確認し、イベントにのみ接続するだけです