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

本文关键字:事件 类型 参数 | 更新日期: 2023-09-27 18:28:53

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

现在,我想为每种特定类型的命令创建类似于event的东西,而不需要在命令中为每种具体类型创建一个事件。指挥官不应与每种类型的命令耦合。

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

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

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

然而,这并不起作用,因为callback不是Action<ICommand>类型,而是Action<AttackCommand>类型。

如何干净地实现这一点?

谢谢!

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

试试这个

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<Type, List<Action<ICommand>>> dictionary = new Dictionary<Type, List<Action<ICommand>>>();
        public void Subscribe<T>(Action<T> callback) where T : ICommand
        {
            Type type = typeof(T);
            List<Action<ICommand>> subscribtions = null;
            dictionary.TryGetValue(type, out subscribtions);
            if (subscribtions == null)
            {
                subscribtions = new List<Action<ICommand>>();
                dictionary.Add(type, subscribtions);
            }
            subscribtions.Add(i => callback((T)i));
        }
        public void Do<T>(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; }
    }
}