不同类型的集合
给定以下界面:
public interface IEventHandler where TEvent : IEvent { void Process(TEvent @event); }
我可以使用什么IEnumerable类型来存储TEvent不同的IEventHandler
实现的集合?
即给出以下3个实现:
public class BlahEvent1EventHandler : IEventHandler { ... } public class WhateverEvent1EventHandler : IEventHandler { ... } public class BlahEvent2EventHandler : IEventHandler { ... }
我可以比一组物品做得更好吗?
var handlers = new List { new BlahEvent1EventHandler(), new WhateverEvent1EventHandler(), new BlahEvent2EventHandler(), };
顺便说一句,已经看到一些其他的答案主张使用基类型或inheritance的非通用接口,但看不出在这种情况下如何增加大量的价值,除非我遗漏了什么。 是的,它会让我以一种稍微更安全的方式将它们全部添加到集合中,使用对象,但不会让我迭代它们并调用强类型的Process方法而不像我需要对象那样进行转换。
public interface IEventHandler { } public interface IEventHandler : IEventHandler where TEvent : IEvent { void Process(TEvent @event); }
如果我有IEnumerable
或IEnumerable
我仍然需要IEnumerable
foreach (var handler in _handlers.Cast<IEventHandler>()) { handler.Process(@event); }
有关如何改善这一点的任何想法?
我认为这里最好的方法是使用OfType扩展方法并保留List,假设在编译时知道事件的类型; 仍然会有一个演员阵容,但你不会这样做,你只会获得可以实际处理该事件的条目。
可能你的设计不是最佳的。 尝试将需要事件类型特定行为的所有代码移动到事件,而不是在事件处理程序中实现它。 即让多态性为你工作。
public interface IEventHandler { void Process(IEvent evt); }
例如,假设您需要根据事件特定属性创建消息。 而不是在事件处理程序内部构造消息,而是在事件中构造它
public interface IEvent { string Message { get; } ... }
特定事件
public class TestEvent : IEvent { public string A { get; set; } // Event specific property public string B { get; set; } // Event specific property public string Message { get { return String.Format("{0} {1}", A, B); } } // The event handler does not need to access A or B. }
UPDATE
让我们假设有一种方法可以按照您的意图定义列表
var handlers = new List>();
你会怎么演员?
var handler = handlers[i]; // How to cast? ((?)handler).Process((?)evt);
也许更好的方法是每个事件类型有一个列表
public static class EventHandler : IEventHandler where TEvent : IEvent { public static readonly List> Handlers = new List>(); ... }
然后你可以访问这样的事件处理程序
SpecificEventType specEvent = ...; EventHandler.Handlers[0].Process(specEvent);
更新#2
一个完全不同的解决方案创建了一个新的集合类,它封装了弱类型列表,并通过使用generics方法提供强类型接口
public class HandlerCollection : IEnumerable { private readonly List
测试
var handlers = new HandlerCollection { new BlahEvent1EventHandler(), new WhateverEvent1EventHandler(), new BlahEvent2EventHandler() }; IEventHandler eh = handlers.Find ();
如果您需要通过处理程序枚举并调用其Process接口成员,那么您可以像这样实现您的类:
public class BlahEvent1EventHandler : IEventHandler { ... } public class WhateverEvent1EventHandler : IEventHandler { ... } public class BlahEvent2EventHandler : IEventHandler { ... } public class Event1 : IEvent {} public class Event2 : IEvent {}
然后使用它们:
List> list = new List>(); list.Add(new BlahEvent1EventHandler()); foreach (IEventHandler eventHandler in list) { eventHandler.Process(new Event1()); }