首页 > 解决方案 > 从通用接口转换为对象返回 null

问题描述

我有这种情况

interface INotification<T>
{
    Task Handle(T t)
}

和多种实现

class Notification1 : INotification<SomeEvent>
{
    //.... 
}


class Notification2 : INotification<SomeEvent>
{
    //.... 
}

我正在使用 ServiceProviderGetServices(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);
    }
}

handlers我得到实现的处理程序INotification<T>在 foreach 循环中,我试图进行强制转换INotification并触发 Handle 方法。

但演员阵容失败

var instance = handler as INotification<TNotification>;

我得到null

我的代码有什么问题?

标签: c#.netdependency-injection.net-coreinversion-of-control

解决方案


基于构造的泛型类型,

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

async Task RunAsync<TEvent>(TEvent @event) {
    var handlers = _serviceProvider.GetServices<INotification<TEvent>>();
    if(handlers.Any()) {
        var tasks = handlers.Select(handler => handler.Handle(@event));
        await Task.WhenAll(tasks);
    }
}

推荐阅读