0

我正在编写一个事件系统,并且在尝试存储不同泛型类型的事件时遇到了一个绊脚石。

事件定义如下:

public delegate void EventHandler<EventInfo>(object sender, EventInfo eventInfo) where EventInfo : IEventInfo;

public interface IEventInfo { }

public interface IEvent<EventInfo> where EventInfo : IEventInfo
{
    void Publish(object sender, EventInfo e);
    void Subscribe(EventHandler<EventInfo> evtHandler);
    void Unsubscribe(EventHandler<EventInfo> evtHandler);
}

public class Event<EventInfo> : IEvent<EventInfo> where EventInfo : IEventInfo
{
    private event EventHandler<EventInfo> eventHandler;

    public void Publish(object sender, EventInfo e)
    {
        if (eventHandler != null)
            eventHandler(sender, e);
    }

    public void Subscribe(EventHandler<EventInfo> evtHandler)
    {
        this.eventHandler -= evtHandler;
        this.eventHandler += evtHandler;
    }

    public void Unsubscribe(EventHandler<EventInfo> evtHandler)
    {
        this.eventHandler -= evtHandler;
    }
}

这个模型似乎适用于订阅和发布,但我实现自己的事件类的主要原因是我可以将它与事件聚合器一起使用,从而使我能够解耦我的组件:

public class EventAggregator
{
    private IDictionary<Type, IEvent<IEventInfo>> dictionary;

    public EventAggregator()
    {
        this.dictionary = new Dictionary<Type, IEvent<IEventInfo>>();
    }

    public EventType GetEvent<EventType>() where EventType : class, IEvent<IEventInfo>, new()
    {
        IEvent<IEventInfo> evt;
        Type evtType = typeof(EventType);
        if (!dictionary.TryGetValue(evtType, out evt))
            dictionary[evtType] = evt = new EventType();
        return evt as EventType;
    }
}

上述函数不适用于派生EventInfo类。例如:

public class FooEventInfo : IEventInfo { }
public class FooEvent : Event<FooEventInfo> { }

EventAggregator ea = new EventAggregator();
var x = ea.GetEvent<FooEvent>(); // Error 3: The type 'TestEvent' cannot be used as type parameter 'EventType' in the generic type or method 'EventAggregator.GetEvent<EventType>()'. There is no implicit reference conversion from 'TestEvent' to 'IEvent<IEventInfo>'.

鉴于和TestEvent : Event<TestEventInfo>,为什么这个演员会失败?Event<TestEventInfo> : IEvent<TestEventInfo>TestEventInfo : IEventInfo

4

2 回答 2

0

因为Event<FooEventInfo>不兼容IEvent<IEventInfo

如果你有一个T'派生自的类型T,那并不意味着A<T'>派生自或以任何方式兼容A<T>

举这个例子

class Animal { ... }
class Dog : Animal { ... }
class Cat : Animal { ... }

List<Animal> animals = new List<Dog>(); // Seems to be possible
animals.Add(new Dog());
animals.Add(new Cat()); // Crashhhh!

添加一个Cattoanimals应该是可能的,但是因为该列表实际上是一个狗列表,所以您会将 a 添加CatDog-list 中!因此这两种类型不能兼容!

于 2012-08-26T16:37:13.390 回答
0

在我看来,您遇到了 C# 不支持协方差的事实。看一下这篇文章,了解 C# 中的协变/逆变,以及他提出的(丑陋的)解决方法。

是对所讨论概念的更深入解释。

于 2012-08-26T16:13:15.830 回答