投射到物体从通用接口返回null

问题描述 投票:1回答:2

我有这种情况

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

和多个实现

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


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

我使用的ServiceProvider的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);
    }
}

handlers我得到实现INotification<T>在foreach循环处理程序,我试图做一个投地INotification并触发手柄方法。

但转换失败

var instance = handler as INotification<TNotification>;

我得到空。

什么是我的代码的问题?

c# .net dependency-injection .net-core inversion-of-control
2个回答
1
投票

根据所构造的通用型,

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);
    }
}

1
投票

var instance = handler as INotification<TNotification>;看起来很奇怪。它看起来像你通常有TNotification作为某种通知类像Notification1的。因此,所得铸造是

    handler as INotification<Notification1>

这的确会失败,因为代码似乎被创建handlerTypeto是TNotification的(在样品箱Notification1),其通常将不Notification1 : INotificaton<Notification1>(也可能 - Recursive generic types)。

你可能想是这样

async Task RunAsync<TNotification, TEvent>(TNotification notification)
       where TNotification : INotification<TEvent>
{
    ...
    var instance = (INotification<TEvent>)handler;
    …
}

请注意,您必须指定事件类型(TEvent)作为单一类可以实现像多接口

class NightWatch :
   INotification<ArrowEvent>, INotification<GunEvent>, INotification<OwlEvent>
{}

有没有办法找出一个施展基于刚刚类。

© www.soinside.com 2019 - 2024. All rights reserved.