C#根据参数类型订阅事件?

我有一个Commander类,它处理命令。 所有这些命令都实现了ICommand接口。 基本上是命令模式……

现在我想为每种特定类型的命令创建类似于event的内容,而不是实际为命令器中的每个特定类型创建event 。 指挥官不应该与每种命令相联系。

所以我的命令有一个方法void Subscribe(Action callback) where T: ICommand 。 如果订户使用void MyAttackCommandHandler(AttackCommand att)作为参数调用它,我希望订阅者只能获得AttackCommands的回调。 但是,另一个类也可以订阅不同的命令。

我尝试创建一个字典,将参数的类型(命令的类型)映射到订阅者列表: Dictionary<Type, List<Action>> _subscriptions ,然后我的subscribe方法看起来像:

 public void Subscribe(Action callback) where T: ICommand { Type type = typeof(T); if (_subscriptions.ContainsKey(type)) { List<Action> subscribtions = _subscriptions[type]; subscribtions.Add(callback); } else ... //create a new entry in _subscriptions } 

但这不起作用,因为callback不是Action类型,而是Action

如何干净利落地实现这一目标?

谢谢!

试试这个

 subscribtions.Add(i => callback((T)i)); 

如果上述方法无效,请提供一个显示问题的完整示例。 像这样的东西:

 using System; using System.Collections.Generic; namespace Example { class Program { static void Main(string[] args) { Commander C = new Commander(); C.Subscribe((MyCommand i) => { Console.WriteLine(i.Value); }); C.Subscribe((SquareMyCommand i) => { Console.WriteLine(i.Value); }); C.Subscribe((SquareMyCommand i) => { Console.WriteLine("**" + i.Value + "**"); }); C.Do(new MyCommand(2));//1 callback , Prints 2 C.Do(new SquareMyCommand(3));//2 callbacks, Prints 9 , **9** Console.ReadLine(); } } public class Commander { Dictionary>> dictionary = new Dictionary>>(); public void Subscribe(Action callback) where T : ICommand { Type type = typeof(T); List> subscribtions = null; dictionary.TryGetValue(type, out subscribtions); if (subscribtions == null) { subscribtions = new List>(); dictionary.Add(type, subscribtions); } subscribtions.Add(i => callback((T)i)); } public void Do(T t) where T : ICommand { foreach (var item in dictionary[t.GetType()]) item(t); } } public class MyCommand : ICommand { public MyCommand(int x) { Value = x; } public int Value { get; set; } } public class SquareMyCommand : ICommand { public SquareMyCommand(int x) { Value = x * x; } public int Value { get; set; } } public interface ICommand { int Value { get; set; } } }