我可以在列表中存储通用方法吗?

时间:2018-05-09 19:11:11

标签: .net list generics

我有一个将通用委托存储到对象列表中的解决方案,但有没有办法将它们存储在类型列表中并避免转换? 我找不到办法,总是得到“找不到命名空间T”这样的错误。

class TestClass {
    public delegate void dEvent<T>(object sender, T value);

    // is it possible to store the generic delegate directly ?
    // List<dEvent<T>> eventlist = new List<dEvent<T>>();

    List<object> objLst = new List<object>();

    public void Subscribe<T> (dEvent<T> ev){
        if (objLst.Contains(ev) == false)
            objLst.Add(ev);
    }

    public void InvokeAll<T>(object sender, T value) {
        foreach (var d in objLst.Where(o => (o as dEvent<T>) != null)) {
            (d as dEvent<T>).Invoke(sender, value);
        }
    }

    static public void StringSubscriber(object sender, string value) {
        Debug.WriteLine(value);
    }
    static public void IntSubscriber(object sender, int value) {
        Debug.WriteLine(value);
    }

    static public void RunTest() {
        TestClass testClass = new TestClass();
        testClass.Subscribe<string>(StringSubscriber);
        testClass.Subscribe<int>(IntSubscriber);
        testClass.InvokeAll<string>(testClass, "Hello");
        testClass.InvokeAll<string>(null, "World");
        testClass.InvokeAll<int>(testClass, 4);
        testClass.InvokeAll<int>(null, 2);
    }       
}

1 个答案:

答案 0 :(得分:0)

这是不可能的,但我喜欢这种方法作为解决方法:

首先创建2个可重用的辅助类:

public abstract class DelegateDef
{
    public abstract Type Type { get; }
}

public class TypedDelegateDef<T> : DelegateDef
{
    private T deleg;
    public T Deleg
    {
        get
        {
            return deleg;
        }
        set
        {
            deleg = value;
        }
    }
    public override Type Type
    {
        get
        {
            return typeof(T);
        }
    }        
}

然后他们可以使用这样的:

class TestClass
{
    public delegate void dEvent<T>(object sender, T value);

    public List<DelegateDef> DelegList = new List<DelegateDef>();

    public void InvokeAll<T>(object sender, T value)
    {
        var list = DelegList.Where(o => (o.Type == typeof(dEvent<T>))).ToList();
        foreach (var d in list)
        {
            TypedDelegateDef<dEvent<T>> s = ((TypedDelegateDef<dEvent<T>>)d);
            ((dEvent<T>)s.Deleg).Invoke(sender, value);
        }
    }

    static public void StringSubscriber(object sender, string value)
    {
        Debug.WriteLine(value);
    }
    static public void IntSubscriber(object sender, int value)
    {
        Debug.WriteLine(value);
    }

    static public void RunTest()
    {
        TestClass testClass = new TestClass();
        testClass.DelegList.Add(new TypedDelegateDef<dEvent<string>>() {Deleg = StringSubscriber });
        testClass.DelegList.Add(new TypedDelegateDef<dEvent<int>>() { Deleg = IntSubscriber });
        testClass.InvokeAll<string>(testClass, "Hello");
        testClass.InvokeAll<string>(null, "World");
        testClass.InvokeAll<int>(testClass, 4);
        testClass.InvokeAll<int>(null, 2);
    }
}

解决方案基于: https://www.roelvanlisdonk.nl/2010/08/31/how-to-mix-generic-classes-in-a-generic-list-in-c/