我正在尝试将更派生的类型作为值添加到字典中<..., base>但出现以下错误: 无法从
HandleIntegrationEvent<TR>
转换为 HandleIntegrationEvent<IBaseEvent>
示例
using System.Threading.Tasks;
using System.Collections.Generic;
public interface IBaseEvent
{
string Name { get; }
}
public class UserCreatedEvent: IBaseEvent
{
public string Name { get; } = "UserCreatedEvent";
}
public delegate Task HandleIntegrationEvent<in TR>(TR @event) where TR: IBaseEvent;
public class IntegrationBus
{
private readonly IDictionary<string, HandleIntegrationEvent<IBaseEvent>> _listeners = new Dictionary<string, HandleIntegrationEvent<IBaseEvent>>();
public void RegisterEventListener<TR>(string @event, HandleIntegrationEvent<TR> listener) where TR: IBaseEvent
{
// ERROR: cannot convert from HandleIntegrationEvent<TR> to HandleIntegrationEvent<IBaseEvent>
_listeners.Add(@event, listener);
}
}
我只是无法理解它,并且已经尝试理解这个问题有一段时间了。 据我了解,通用约束应该确保实例已实现 IBaseEvent 接口。
我只是暂时有心理障碍
编辑 发现另一篇很棒的文章https://stackoverflow.com/a/12841831解释了字典协方差和逆变的原因。 但我还是有点迷茫
您需要更改字典以存储
Func<IBaseEvent, Task>
而不是HandleIntegrationEvent<IBaseEvent>
。然后,在添加到字典时,用 Func<IBaseEvent, Task>
包装侦听器以将事件转换为适当的类型。
更新代码:
private readonly IDictionary<string, Func<IBaseEvent, Task>> _listeners = new Dictionary<string, Func<IBaseEvent, Task>>(); //add using System; if you get an Func<> error
public void RegisterEventListener<TR>(string @event, HandleIntegrationEvent<TR> listener) where TR : IBaseEvent
{
_listeners.Add(@event, (e) => listener((TR)e));
}