问题描述
我决定为我正在编写的 winforms MVP 应用程序构建我自己的事件聚合器.目的是允许视图(用户控件)订阅来自模型的事件,否则模型拥有它们的视图.
I have decided to build my own event aggregator for a winforms MVP application I am writing.The purpose is to allow views (user controls) to subscribe to events from models that otherwise have their views.
问题是;既然应该有一个通用的事件聚合器,并且只有在编写应该交互的用户控件的应用程序时才需要聚合器,那么暴露事件聚合器的最佳方式是什么?
The question is; since there should be one common event aggregator, and the aggregator is only needed when composing the application of user controls that should interact, then what is the best way of exposing the event aggregator?
到目前为止我的建议:
- 我认为注入它会很麻烦,因为所有用户控件都必须有一个 IEventAggregator,而用户控件本身不需要聚合器,只需要由具有附加功能的用户控件组成的主应用程序.立>
- 使 EventAggregator 成为静态或单例.但是,这会带来类似的问题,即各个用户控件必须通过静态聚合器发布事件.
你有什么想法可以帮助我吗?
Do you have some ideas to help me along?
推荐答案
我已经为这样的场景实现了一个简单的 EventBroker.但是,我认为注射不会一团糟.事实上,将其注入容器然后解析为发布/订阅将是最简洁的方式.单元测试也会更容易.我的事件代理如下(我正在使用 MEF,但这几乎没有任何区别):-
I had implemented a simple EventBroker for such a scenario. However, I don't think injecting would be a mess. Infact, injecting it to the container and then resolving to publish/subscribe would be the neatest way. Would be easier to unit test as well. My Event Broker is given below (I am using MEF, bu this will hardly make any difference):-
[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
{
}
现在有你的自定义事件,定义你的事件参数:-
Now to have your custom event, define your event args:-
#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 是我的自定义单例类,用于公开组合容器.你可以使用 unity、windsor 或任何你喜欢的东西!
MefContainer is my custom singleton class to expose the composition container. You can use unity, windsor or whatever you like!
在这里写了博客:http://compositewinform.blogspot.co.uk/2014/04/have-you-ever-found-yourself-in.html
这篇关于winforms MVP 应用程序中的自定义事件聚合器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!