Не удается разрешить реализованный объект при использовании универсального типа в asp.net .core - PullRequest
0 голосов
/ 25 декабря 2018

Моя проблема проста!Как я могу разрешить вручную этот зарегистрированный интерфейс:

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

Примечание : Для разрешения ServiceLocator и DbiContainer сначала я помещаю их в Configure метод StartUp

1 Ответ

0 голосов
/ 26 декабря 2018

Краткий ответ: это потому, что вы создаете другой ServiceProvider, отличный от стандартного .Обратите внимание на следующий код:

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

Это означает, что вы будете использовать коллекцию сервисов для создания нового ServiceProvider, а затем передать это ServiceProvider в ProviderDiContainer. В результате любые сервисы, зарегистрированные ниже этой строки, не будут решаться ProviderDiContainer.

Как исправить

  1. Вместо того, чтобы запрашивать конкретную реализацию, мы должны зависеть от абстракции (интерфейса):
    public class ProviderDiContainer: IDiContainer {

        <strike>private readonly ServiceProvider _container; </strike>
        private readonly IServiceProvider _container;

        <strike>public ProviderDiContainer(ServiceProvider container) </strike>
        public ProviderDiContainer(IServiceProvider container)
        {
            _container = container;
        }

        public T Resolve<T>()
        {        
            return _container.GetService<T>();
        }
    }
Не строить ненужных ServiceProvider:
    <strike>var diContainer = new ProviderDiContainer(services.BuildServiceProvider());</strike>
    <strike>services.AddSingleton<IDiContainer>(c => diContainer);</strike>
    <strike> ... </strike>
    <strike>services.AddSingleton(s => new ServiceLocator(diContainer));</strike>
    services.AddSingleton<IDiContainer>(sp => new ProviderDiContainer(sp));
    services.AddSingleton<ServiceLocator>();
...