2012-08-09 35 views
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>' 

回答

5

編輯:它實際上是ISubscribe是協變了需要 - 但現在我們能看到的ISubscribe聲明,你不能使它協變 - 只有逆變。

一般來說,類型不是一般的變體。例如,ICollection<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); 
     } 
    } 
} 
+0

如果我加入了協變到IEVent它去猿市 任何指針? – iwayneo 2012-08-09 16:50:20

+0

@iwayneo:道歉,它是'ISubscribe',它需要協變 - 編輯。 – 2012-08-09 16:54:08

+0

但是然後我得到無效方差:類型參數'T'必須是衝突有效 – iwayneo 2012-08-09 16:55:35