I have some class libraries that provide services to the applications I create and for legacy reasons they are tightly bound to DryIoc. That is, the service registrations are tightly bound, not the actual services.
If I can I would rather not just go around changing that code if I don't have to.
Creating a new ASP.NET MVC Core application I was able to use DryIoc by changing the ConfigureServices method to return an IServiceProvider like this:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddControllersAsServices();
var container = new Container().WithDependencyInjectionAdapter(services);
return container.ConfigureServiceProvider<CompositionRoot>();
}
(this is from memory so may not be 100% correct but that is not important)
The important change was that the void
method could be changed to return an IServiceProvider
, which DryIoc
can provide me with.
However, with HostBuilder
, which I want to use for console applications, background services, etc. the method that configures services doesn't accept IServiceProvider
so I'm not sure how to do it.
The important code is this:
var builder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) => { ... })
.ConfigureServices((hostContext, services) =>
{
services.AddOptions();
// configure services
})
.ConfigureLogging((hostingContext, logging) => { ... });
The ConfigureServices
method above has one overload and an extension method:
ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
ConfigureServices(this IHostBuilder hostBuilder, Action<IServiceCollection> configureDelegate)
There doesn't seem to be any provisions for returning or using a IServiceProvider
or anything else that DryIoc
could provide for me in this regard.
Is this possible? Is there a way to bridge the gap? Or do I just have to switch to using the Microsoft IServiceCollection
for my class libraries? Since they are in use in many projects I'd rather not change just because it seems easiest in this specific instance, but if I have to, I have to.
An answer, that was incorrect (but correct in the context of an ASP.NET application), was provided by @Nkosi, and the comment thread sparked a discussion about a method UseServiceProviderFactory
that turned out to be the solution, so thanks guys.
To use UseServiceProviderFactory
I had to implement one class myself, and add the appropriate nuget package references to my project.
Here are the steps:
DryIoc.dll
(unsurprisingly)DryIoc.Microsoft.DependencyInjection
UseServiceProviderFactory
The original code looked like this:
var builder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) => { ... })
.ConfigureServices((hostContext, services) =>
{
services.AddOptions();
// configure services
})
.ConfigureLogging((hostingContext, logging) => { ... });
Here's what to use instead:
var builder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) => { ... })
.ConfigureServices((hostContext, services) =>
{
services.AddOptions();
// configure services
})
//////////////////// ADD THIS vvvvvvvv
.UseServiceProviderFactory(new DryIocServiceProviderFactory())
.ConfigureContainer<Container>((hostContext, container) =>
{
container.Register<...>();
})
//////////////////// ADD THIS ^^^^^^^^
.ConfigureLogging((hostingContext, logging) => { ... });
Then supply this implementation of DryIocServiceProviderFactory
:
internal class DryIocServiceProviderFactory : IServiceProviderFactory<IContainer>
{
public IContainer CreateBuilder(IServiceCollection services)
=> new Container().WithDependencyInjectionAdapter(services);
public IServiceProvider CreateServiceProvider(IContainer containerBuilder)
=> containerBuilder.ConfigureServiceProvider<CompositionRoot>();
}
The CompositionRoot
class above is resolved during configuration and the constructor can be used to configure the container. A dummy-class that does nothing can be used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With