【问题标题】:Event Aggregator: need help modifying solution事件聚合器:需要帮助修改解决方案
【发布时间】:2011-12-05 17:33:40
【问题描述】:

我正在尝试为我的应用程序设计一个事件聚合器。 (我是设计模式的新手,所以我可能还没有完全理解它。

首先,我已经创建了一个解决方案,它在某种程度上是一个聚合器,但需要改进和重构以实现更高的效率并减少依赖性。

1) 在事件聚合器设计模式中,我的 .NET 数据源是否会被视为发布者? (我不确定出版商的角色是)。

2) 我将如何设计我的解决方案来处理不仅对特定数据源的订阅,而且还能处理特定数据事件而忽略其他事件?我希望看到一种解决方案,它可以摆脱保留列表并不知疲倦地循环遍历它们。但不确定我是否可以一起避免这种情况。

【问题讨论】:

    标签: .net design-patterns refactoring eventaggregator


    【解决方案1】:

    我认为你必须在这里实现一个好的发布者/订阅者。我的建议是这样的:

    您的发布者:EventAggregator 应该有如下方法:

    public void Register(IEventObserver observer, EventFilter filter)
    public void Unregister(IEventObserver observer)
    

    你的IEventObserver 应该是这样的

    public interface IEventObserver
    {
        void Notify(object eventSource, DetailedEventArgs e);
    }
    

    你的订阅者应该实现这个接口。

    您的EventFilter 类应该具有您打算使用的所有过滤属性。 这个类可以有这样的方法:

    public bool IsSatisfiedBy(DetailedEventArgs e)
    

    并创建一个名为DetailedEventArgs 的类并从EventArgs 继承它,将您想要的有关事件的所有详细信息放在上面。

    Register 方法中,您应该同时存储过滤器和观察器。现在当你的EventAggregator 捕捉到一个事件时,它应该首先从接收到的事件中创建DetailedEventArgs 对象,然后循环观察者及其过滤器以查看对象是否满足过滤器,如果满足,则调用 Notify 方法原始发送者和DetailedEventArgs对象的观察者。

    我强烈建议您检查发布方而不是订阅方的过滤器。因为在订阅者端签入会导致大量代码重复和不一致。

    编辑:EventFilterDetailedEventArgs 类的示例:

    public class EventFilter
    {
        private List<Type> SourceTypes;
        private List<EventType> EventTypes;
        public EventFilter() : this(new Type[] { }, new EventType[] { }) { }
        public EventFilter(IEnumerable<Type> sourceTypes, IEnumerable<EventType> eventTypes)
        {
            SourceTypes = new List<Type>(sourceTypes);
            EventTypes = new List<EventType>(eventTypes);
        }
        public void AddSourceType(Type type)
        {
            AddItemToList(SourceTypes, type);
        }
        public void AddEventType(EventType type)
        {
            AddItemToList(EventTypes, type);
        }
        private void AddItemToList<T>(List<T> list, T item)
        {
            lock (list)
            {
                if (!list.Contains(item))
                    list.Add(item);
            }
        }
        public bool IsSatisfiedBy(DetailedEventArgs args)
        {
            return SourceTypes.Contains(args.Source.GetType()) && EventTypes.Contains(args.EventType);
        }
    }
    public class DetailedEventArgs : EventArgs
    {
        public EventArgs SourceArgs { get; private set; }
        public object Source { get; private set; }
        public EventType EventType { get; private set; }
        public DetailedEventArgs(object source, EventArgs sourceArgs, EventType eventType)
        {
            Source = source;
            SourceArgs = sourceArgs;
            EventType = eventType;
        }
    }
    public enum EventType
    {
        EventType1,
        EventType2,
        EventType3
    }
    

    希望我能帮上忙 :)

    【讨论】:

    • 我不完全确定这个 EventFilter 的结构应该是什么样的(以及将存储什么信息)。为了清楚起见,您能否提供一个示例来说明它的外观?
    • 编辑了答案并添加了一个示例。在我的示例中,EventFilter 类与 Type 的源一起使用,但如果需要,您可以将它们更改为对象以检查源实例。
    【解决方案2】:

    查看MVVM Light Messenger 课程。我的实现基于此。但是,它使用列表和循环,但我没有看到解决方法。

    我看到了一些关于内存泄漏的投诉,但它并没有影响到我,并且可能会得到修复。

    【讨论】:

    • 这个地址是#2吗? (订阅者忽略了来自数据源的某些事件,同时仍在收听其他事件?)
    • 是的。 register 方法有一个泛型类型。只有该类型的邮件才会发送给该收件人。
    • 谢谢,我会调查一下,看看是否可以帮助我。我暂时不会选择答案;直到我确定这可能会有所帮助。 (并查看其他人是否发布答案)。非常感谢! :D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    相关资源
    最近更新 更多