我有这种情况
function someFunc() {
alert("function loaded!!")
}
someFunc(); // will load on page load
document.getElementById("ano").addEventListener("click", someFunc); // will load when `ano` element invokes the change listener
和多种实现方式
<button id="ano">Click Me</button>
我正在使用ServiceProvider的interface INotification<T>
{
Task Handle(T t)
}
来获取所有实现
这样
class Notification1 : INotification<SomeEvent>
{
//....
}
class Notification2 : INotification<SomeEvent>
{
//....
}
在GetServices(Type)
中,我获得了实现async Task RunAsync<TNotification>(TNotification notification)
{
Type notificationType = notification.GetType();
var handlerType = typeof(INotification<>).MakeGenericType(notificationType);
var handlers = _serviceProvider.GetServices(handlerType);
foreach (var handler in handlers)
{
var instance = handler as INotification<TNotification>;
await instance.Handle(notification);
}
}
的处理程序。在foreach循环中,我试图对handlers
进行强制转换并触发Handle方法。
但是强制转换失败
INotification<T>
我得到 null 。
我的代码有什么问题?
答案 0 :(得分:1)
var instance = handler as INotification<TNotification>;
看起来很奇怪。看起来您通常将TNotification
作为某种通知类,例如Notification1
。因此,结果转换为
handler as INotification<Notification1>
的确会失败,因为代码似乎正在创建handlerType
的{{1}}(在示例情况下为TNotification
),通常不会是Notification1
(也可能- Recursive generic types。
您可能想要类似
Notification1 : INotificaton<Notification1>
请注意,您必须指定事件类型(async Task RunAsync<TNotification, TEvent>(TNotification notification)
where TNotification : INotification<TEvent>
{
...
var instance = (INotification<TEvent>)handler;
…
}
),因为单个类可能实现多个接口,例如
TEvent
并且无法根据类来确定要投射到哪个对象。
答案 1 :(得分:1)
基于构造的通用类型
UNION
我相信泛型可能会引起混淆。
请考虑为服务提供商使用通用的var handlerType = typeof(INotification<>).MakeGenericType(notificationType);
扩展名,该扩展名将简化以上代码。
GetServices<T>()
由于具有强类型的泛型,因此简化了对处理程序的调用,因为它们已经是所需的类型
这也可以重构为使用async Task RunAsync<TEvent>(TEvent @event) {
var handlers = _serviceProvider.GetServices<INotification<TEvent>>();
foreach (var handler in handlers) {
await handler.Handle(@event);
}
}
异步处理所有通知,而不是像Task.WhenAll
循环那样按顺序
foreach