2

なぜこれが機能しないのですか?!

    public interface IBus
    {
        void Subscribe<T>(ISubscribe<T> subscriber) where T : class, IEvent;
        void Send<T>(IEvent @event) where T : class, IEvent;
    }

    class InMemoryEventBus : IBus
    {
        private readonly IDictionary<ISubscribe<IEvent>, Type> _subscribers;

        public InMemoryEventBus()
        {
            _subscribers= new Dictionary<ISubscribe<IEvent>, Type>();
        }

        public void Subscribe<T>(ISubscribe<T> subscriber) where T : class, IEvent
        {
            _subscribers.Add(subscriber, typeof(T));
        }

        public void Send<T>(IEvent @event) where T : class, IEvent
        {
            foreach (var subscriber in _subscribers.Where(subscriber => subscriber.Value == typeof(T)))
            {
                subscriber.Key.Handle(@event);
            }
        }
    }

    public interface IEvent
    {
        Guid EventId { get; set; }
    }

    public interface ISubscribe<T> where T : IEvent
    {
        void Handle(T @event);
    }

    public class StockLevelDroppedBellowMinimumLevelEvent : IEvent
    {
        public Guid EventId { get; set; }

        public string Message { get; set; }
    }

私は得る:

cannot convert from 'IHandle<T>' to 'IHandle<IEvent>'
4

1 に答える 1

4

編集:実際にはISubscribeどちらが共変である必要がありました-しかし、 の宣言を見ることISubscribeができるようになったので、共変にすることはできません-反変のみです。

一般に、型は一般的にバリアントではありません。たとえば、 anICollection<string>は - ではありません。ICollection<object>これは良い仕事です。それ以外の場合は、次のようにコンパイルされます。

ICollection<string> strings = new List<string>();
ICollection<object> objects = strings; // Fortunately this isn't valid
objects.Add(new Button()); // This should be fine of course...
string x = strings[0]; // But what would this do?!

あなたの場合、辞書を変更する必要があると思います-ISubscribeそれぞれの場合に「正しい」タイプが使用されることを保証できます。ただし、辞書を非常に奇妙な方法で使用しています。次のように、キーと値の型を逆にする必要があります。

class InMemoryEventBus : IBus
{
    private readonly IDictionary<Type, object> _subscribers;

    public InMemoryEventBus()
    {
        _subscribers = new Dictionary<Type, object>();
    }

    public void Subscribe<T>(ISubscribe<T> subscriber) where T : IEvent
    {
        _subscribers.Add(typeof(T), subscriber);
    }

    public void Send<T>(IEvent @event) where T : class, IEvent
    {
        object value;
        if (_subscribers.TryGetValue(typeof(T), out value))
        {
             ISubscriber<T> subscriber = (ISubscriber<T>) value;
             subscriber.Handle(@event);
        }
    }
}
于 2012-08-09T16:42:47.777 に答える