1

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 Answer 1

1

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>();
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! The gold key was sp => new ProviderDiContainer(sp). I thought that BuildServiceProvider returns the current provider.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.