Cannot resolve implemented object while using gene

2019-09-01 13:36发布

My problem is simple! How can I resolve manually this registered interface:

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

This code not work and always return null:

My DiContainer is like this:

public class ProviderDiContainer : IDiContainer
{
    private readonly ServiceProvider _container;

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

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

Which is registered such:

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

And my Service Locator is:

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

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

Now when I call this code it returns null to me:

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

Note: To resolve ServiceLocator and DbiContainer at first, I put them in Configure method of the StartUp

1条回答
趁早两清
2楼-- · 2019-09-01 14:15

Short answer: that' because you're building an another ServiceProvider which is different from the default one . Note the following code :

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

That means the you'll use the services collection to build a new ServiceProvider, and then pass that ServiceProvider to ProviderDiContainer. As a result, any services registered below that line will not be resolved by the ProviderDiContainer.

How to fix

  1. Instead of asking for a specific implementation, we should depends on abstraction (interface):
    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. Don't build unnecessary 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>();
查看更多
登录 后发表回答