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

C#が共分散をサポートしていないという事実に遭遇しているように私には聞こえます。この投稿を見て、C#の共変性/反変性、および彼が思いついた(醜い)回避策について読んでください。

ここに問題の概念のより深い説明があります。

于 2012-08-26T16:13:15.830 に答える
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!

Cattoを追加することanimalsは可能ですが、リストは実際には犬のリストであるためCatDog-listに追加することになります。したがって、2つのタイプは互換性がありません!

于 2012-08-26T16:37:13.390 に答える