このようなシナリオのために、単純な EventBroker を実装しました。でも、注射は悪くないと思います。実際、それをコンテナに注入してから、パブリッシュ/サブスクライブに解決するのが最も適切な方法です。単体テストも簡単になります。私のイベント ブローカーは以下のとおりです (私は MEF を使用していますが、ほとんど違いはありません):-
[Export]
public class MyEventBroker : IMyEventBroker
{
[ImportingConstructor]
public MyEventBroker()
{
}
private readonly ConcurrentDictionary<Type, List<Action<CompositeEventArguments>>> _compositeEventHandlers = new ConcurrentDictionary<Type, List<Action<CompositeEventArguments>>>();
public void Publish<T>(CompositeEventArguments args)
{
if (_compositeEventHandlers.ContainsKey(typeof (T)))
{
_compositeEventHandlers[typeof(T)].ForEach(subscriber=> { if (subscriber != null) subscriber.Invoke(args); }); //TODO : check for null. QUES - Will we need weak references?????
}
}
public void Subscribe<T>(Action<CompositeEventArguments> handler)
{
if (!_compositeEventHandlers.ContainsKey(typeof (T)))
_compositeEventHandlers[typeof(T)] = new List<Action<CompositeEventArguments>>();
_compositeEventHandlers[typeof (T)].Add(handler);
}
public void UnSubscribe<T>(Action<CompositeEventArguments> handler)
{
if (_compositeEventHandlers.ContainsKey(typeof (T)))
_compositeEventHandlers[typeof (T)].Remove(handler);
}
}
public class CompositeEvent<T> where T : CompositeEventArguments
{
}
public class CompositeEventArguments
{
}
カスタムイベントを作成するには、イベント引数を定義します:-
#region Custom Events
public class MyCustomEventArgs : CompositeEventArguments{}
#endregion
次に公開します:-
var broker = MefContainer.Instance.Resolve<MyEventBroker>();
broker.Publish<MyCustomEventArgs >(new MyCustomEventArgs());
そして購読するには: -
var broker = MefContainer.Instance.Resolve<MyEventBroker>();
broker.Subscribe<MyCustomEventArgs >(t=>MyHandler(t));
MefContainer は、コンポジション コンテナーを公開するためのカスタム シングルトン クラスです。ユニティ、ウィンザー、または好きなものを使用できます。
これについてのブログ: http://compositewinform.blogspot.co.uk/2014/04/have-you-ever-found-yourself-in.html