Implement IServiceProviderFactory for use in generic hosts
Closed this issue Β· 12 comments
It seems that if you want to use LightInject with the new generic host in .NET Core 2.1 (Microsoft.Extensions.Hosting) , you have to provide an implementation of IServiceProviderFactory in LightInject.Microsoft.DependencyInjection.
Have a look here: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.1#container-configuration
(note the text at the start of the page: "The Generic Host is under development to replace the Web Host in a future release and act as the primary host API in both HTTP and non-HTTP scenarios.).
Something like
public static IHostBuilder UseLightInject(this IHostBuilder hostBuilder)
{
hostBuilder.UseServiceProviderFactory(new LightInjectServiceProviderFactory());
return hostBuilder;
}
public class LightInjectServiceProviderFactory : IServiceProviderFactory<ServiceContainer>
{
private IServiceCollection _services;
private ServiceContainer _serviceContainer;
public ServiceContainer CreateBuilder(IServiceCollection services)
{
_services = services;
_serviceContainer = new ServiceContainer();
return _serviceContainer;
}
public IServiceProvider CreateServiceProvider(ServiceContainer containerBuilder)
{
var provider = containerBuilder.CreateServiceProvider(_services);
var lifetime = provider.GetService<IApplicationLifetime>();
lifetime.ApplicationStopped.Register(() => _serviceContainer.Dispose()); //If I don't do this the process will hang when I terminate it (ctrl+c)
return provider;
}
}
I think this actually calls for a new package as it is not really part of the dependency injection abstractions.
Maybe something like LightInject.Microsoft.AspNetCore.Hosting
Hi Bernhard
IServiceProviderFactory is part of Microsoft.Extensions.DependencyInjection(.Abstractions) and is used by IHostBuilder which is part of Microsoft.Extensions.Hosting(.Abstractions), so it is not a ASP.NET thing :-)
Hi @seesharper,
I was wondering if there has been any progress made on this issue? I'm in the process of building an app using the .NET Core 2.1 Generic Host with LightInject as the DI container but have encountered the failure to exit problem.
I've tried the code suggested above on 28th May 2018 (registering with IApplicationLifetime.ApplicationStopped) but this doesn't solve the failure to shutdown the app. The registered delegate function is getting called during app shutdown and calls .Dispose() on the service container.
I was wondering if it was something to do with the container root Scope begun by the CreateServiceProvider extension method not being ended, but my knowledge of the internals of how LightInject works is admittedly limited.
Any suggestions would be appreciated.
Typically, after spending over a day looking at this I manage to solve it within minutes of posing the question.
I modified the code from above to this:
public class LightInjectServiceProviderFactory : IServiceProviderFactory<ServiceContainer>
{
private IServiceCollection _services;
private ServiceContainer _serviceContainer;
public ServiceContainer CreateBuilder(IServiceCollection services)
{
_services = services;
_serviceContainer = new ServiceContainer();
return _serviceContainer;
}
public IServiceProvider CreateServiceProvider(ServiceContainer containerBuilder)
{
var provider = containerBuilder.CreateServiceProvider(_services);
var lifetime = provider.GetService<IApplicationLifetime>();
lifetime.ApplicationStopped.Register(() =>
{
_serviceContainer.Dispose();
_serviceContainer.ScopeManagerProvider.GetScopeManager(_serviceContainer)
.CurrentScope.Dispose();
}); //If I don't do this the process will hang when I terminate it (ctrl+c)
return provider;
}
}
Please let me know if I'm doing something massively wrong here.
@goldenbeard I don't think you are doing anything massively wrong πThe LightInject adapter creates a "root" scope which probably would have to be disposed. As long as it works it should be okay. After all this is just before the app ends π
ServiceProviderFactory is part of Microsoft.Extensions.DependencyInjection(.Abstractions) and is used by IHostBuilder which is part of Microsoft.Extensions.Hosting(.Abstractions), so it is not a ASP.NET thing :-)
No but the UseLightInject
extension method from LightInject.Microsoft.AspNet.Hosting
extends the IWebHostBuilder
and not the IHostBuilder
which is the generic host. Hence the need for another package. The reason I've put this on hold is that the word on the street is that everything will eventually be based on the generic host. But up until now this is somewhat unclear. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2
Seems like it is coming though
aspnet/Hosting#1580 (comment)
@davidfowl This is something coming in 3.0, right?
Yep!
Hi @seesharper,
Correct me if I'm wrong, but it doesn't appear that any of the content discussed in this issue is resolved in the new release of seesharper/LightInject.Microsoft.AspNetCore.Hosting?
Hi again @goldenbeard
The IServiceProviderFactory
was introduced here
3f23546#diff-4205119d44407f0a3d99f06bfb799c73
Its implementation is in this repo so that it can be used outside of a web host.
For a .Net3.0 generic host we can do something like
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.UseServiceProviderFactory(new LightInjectServiceProviderFactory());
We could of course have create a package called LightInject.Microsoft.Hosting
and had a UseLightInject
extending the IHostBuilder
. That would be a very small package though since it will basically just call into UseServiceFactory
π
So for generic hosts, we don't need the LightInject.Microsoft.AspNetCore.Hosting
package. Only the LightInject.Microsoft.DependencyInjection
package.