在asp.net .core中使用通用类型时,无法解析实现的对象

时间:2018-12-25 12:02:30

标签: generics asp.net-core dependency-injection

我的问题很简单! 如何手动解决此注册界面:

services.AddScoped<ICommandHandler<Command>, AddProductCommandHandler>();

此代码无效,并且始终返回null

我的DiContainer是这样的:

public class ProviderDiContainer : IDiContainer
{
    private readonly ServiceProvider _container;

    public ProviderDiContainer(ServiceProvider container)
    {
        _container = container;
    }

    public T Resolve<T>()
    {        
       return _container.GetService<T>();
    }
}

已注册的人:

public void ConfigureServices(IServiceCollection services)
{            
    var diContainer = new ProviderDiContainer(services.BuildServiceProvider());
    services.AddSingleton<IDiContainer>(c => diContainer);
//  Register some other things here      Registrar.RegisterSomethings(services);
    services.AddSingleton(s => new ServiceLocator(diContainer));
}

我的服务定位器是:

public class ServiceLocator
{
    public ServiceLocator(IDiContainer container)
    {
            Current = container;
    }

    public static IDiContainer Current
    {
        get;
        private set;
    }
}

现在,当我调用此代码时,它会向我返回null

var commandHandler = ServiceLocator.Current.Resolve<ICommandHandler<TCommand>>();

注意:首先要解决ServiceLocatorDbiContainer的问题,我将它们放在StartUp的Configure方法中

1 个答案:

答案 0 :(得分:1)

简短的回答:那是因为您要构建另一个ServiceProvider,它不同于默认的。请注意以下代码:

var diContainer = new ProviderDiContainer(services.BuildServiceProvider());

这意味着您将使用服务集合来构建新的ServiceProvider,然后将该ServiceProvider传递给ProviderDiContainer因此,ProviderDiContainer将无法解决该行下方注册的任何服务。

如何修复

  1. 代替要求特定的实现,我们应该依靠抽象(接口):
    public class ProviderDiContainer: IDiContainer {

        private readonly ServiceProvider _container; 
        private readonly IServiceProvider _container;

        public ProviderDiContainer(ServiceProvider container) 
        public ProviderDiContainer(IServiceProvider container)
        {
            _container = container;
        }

        public T Resolve<T>()
        {        
            return _container.GetService<T>();
        }
    }
  1. 不要构建不必要的ServiceProvider
    var diContainer = new ProviderDiContainer(services.BuildServiceProvider());
    services.AddSingleton<IDiContainer>(c => diContainer);
     ... 
    services.AddSingleton(s => new ServiceLocator(diContainer));
    services.AddSingleton<IDiContainer>(sp => new ProviderDiContainer(sp));
    services.AddSingleton<ServiceLocator>();