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

C#根据参数类型订阅事件?,c#,C#,我有一个Commander类,它处理命令。所有这些命令都实现了ICommand接口。基本上是命令模式 现在,我想为每个特定类型的命令创建类似于事件的内容,而不实际为指挥官中的每个特定类型创建事件。指挥官不应与每种类型的命令相耦合 因此,我的命令有一个方法voidsubscribe(actioncallback),其中T:ICommand。如果订阅者使用方法void MyAttackCommandHandler(AttackCommand att)作为参数调用此函数,我希望订阅者仅为AttackC

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

现在,我想为每个特定类型的命令创建类似于
事件的内容,而不实际为指挥官中的每个特定类型创建事件。指挥官不应与每种类型的命令相耦合

因此,我的命令有一个方法
voidsubscribe(actioncallback),其中T:ICommand
。如果订阅者使用方法
void MyAttackCommandHandler(AttackCommand att)
作为参数调用此函数,我希望订阅者仅为
AttackCommands
获得回调。但是,另一个类也可以订阅不同的命令

我尝试创建一个字典,它将参数的类型(命令的类型)映射到订阅者列表:
dictionary\u subscriptions
,然后我的subscribe方法如下所示:

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
}
public void Subscribe(操作回调)
其中T:ICommand
{
类型=类型(T);
if(_subscriptions.ContainsKey(类型))
{
列表订阅=_订阅[类型];
subscribtions.Add(回调);
}
else…//在\订阅中创建一个新条目
}
但是,这不起作用,因为
回调
不是
操作
类型,而是
操作
类型

如何干净地实现这一点

谢谢

试试这个

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; }
    }
}
使用系统;
使用System.Collections.Generic;
名称空间示例
{
班级计划
{
静态void Main(字符串[]参数)
{
指挥官C=新指挥官();
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(新的MyCommand(2));//1回调,打印2
C.Do(新的SquareMyCommand(3));//2次回调,打印9,**9**
Console.ReadLine();
}
}
公营班长
{
字典=新字典();
public void Subscribe(操作回调),其中T:ICommand
{
类型=类型(T);
列表subscribtions=null;
TryGetValue(类型,外下标);
if(subscribtions==null)
{
subscribtions=新列表();
添加(类型、订阅);
}
Add(i=>callback((T)i));
}
公共无效Do(T T),其中T:ICommand
{
foreach(字典[t.GetType()]中的变量项)
项目(t);
}
}
公共类MyCommand:ICommand
{
公共MyCommand(int x){Value=x;}
公共int值{get;set;}
}
公共类SquareMyCommand:ICommand
{
公共SquareMyCommand(int x){Value=x*x;}
公共int值{get;set;}
}
公共接口ICommand
{
int值{get;set;}
}
}

你的
AttackCommand
实现了
ICommand
对吗?如果你有一个像
BaseCommand
这样的基类,它实现了
ICommand
,并且有
AttackCommand
扩展
BaseCommand
应该可以工作?@Rahul这是正确的。那么它应该工作得很好,因为attackcomand是我命令。@Rahul不,没有。你把它倒过来了。问题是ICommand不是AttackCommand。(尽管AttackCommand是一个ICommand:P),因此您不能将操作添加到操作列表中。列表要求其中的所有操作都接受所有类型的命令,我尝试添加一个只接受攻击命令的操作。您可能希望添加一些解释,说明为什么在问题示例中这样做有效。