My application is based on ASP.NET Core 2.1 and .NET Core 2.1 (downgraded from 2.2) generic host as Windows Service. So, IHostBuilder is launched first with other services and frameworks and then (if role permits) web service gets launched on top using IWebHostBuilder with all that WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().StartAsync(). Secondary WebHost is another story; it is initialized and works, but I haven't checked yet if IoC replacement has the same trouble as generic host.
For now, generic host initialization:
new HostBuilder().ConfigureServices((hostContext, services) =>
{
services.AddHostedService<LifetimeService>(); // Gets launched when host is up
var container = ContainerBuilder.BuildBaseContainer(services, new WorkingPath());
services.AddSingleton<IContainer>(container);
services.AddStructureMap(); // Has no effect
});
IContainer initialization:
public static Container BuildBaseContainer(IServiceCollection services, IWorkingPath workingPath)
{
var container = new Container();
container.Configure(config =>
{
config.Scan(scan =>
{
workingPath.OwnLoadedAssemblies.Where(asm => !asm.IsDynamic).ForEach(scan.Assembly);
scan.LookForRegistries();
scan.AddAllTypesOf<IPlatformService>();
});
config.For<IContainer>().Use(() => container);
config.Populate(services);
});
container.AssertConfigurationIsValid();
return container;
}
And the trouble is here, in the constructor of that registered hosted service (or anywhere else)
public LifetimeService(IEnumerable<IPlatformService> services,
IServiceProvider sp, IContainer c)
{
var inCollection = services.Any();
var inContainer = c.TryGetInstance<IPlatformService>() != default;
var inProvider = sp.GetRequiredService<IPlatformService>() != default;
}
ps: IServiceProvider and IContainer are for demonstration purposes only, I only need 'services'
When LifetimeService is initialized during container.AssertConfigurationIsValid() I get
inCollection is true
inContainer is true
inProvider is true
IServiceProvider is StructureMapServiceProvider
Actual LifetimeService execution shows that
inCollection is false
inContainer is true
inProvider is false
IServiceProvider is ServiceProviderEngineScope
I don't plan to pass IServiceProvider or IContainer into constructors, but it seems that dependencies are resolved using IServiceProvider, not IContainer, and I get nulls. Silly thing like sp.GetRequiredService<IContainer>().TryGetInstance<IPlatformService>() does work.
There been some happy-path examples using WebHost and Startup classes where injection ought to be working properly. Doesn't seem relevant for generic host ...which might replace WebHost one day, but is little known and not widely used. Well, could be due to .NET Core version downgrade too, but quite unlikely. I've also tried replacing IServiceProvider and IServiceScopeFactory from IContainer during ConfigureServices() without luck. My idea is to replace or forward internal container to StructureMap. I might be misunderstanding how that should work...
Has anyone successfully tried to 'marry' generic host and external IoC?