为什么这不起作用?!
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>'
答案 0 :(得分:4)
编辑:实际上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);
}
}
}