aspnet / Hosting

[Archived] Code for hosting and starting up an ASP.NET Core application. Project moved to https://github.com/aspnet/Extensions and https://github.com/aspnet/AspNetCore
Apache License 2.0
552 stars 312 forks source link

Provide a way to supply an external IServiceCollection to WebHostBuilder #1349

Closed eisendle closed 6 years ago

eisendle commented 6 years ago

I´m writting a server framework which has the ability to load extensions (modules). The framework creates a ServiceCollection and during the extension lifecycle the service collection is passed to the extensions to register their services. One of these extensions utilizes asp.net core. It´s problematic that there is no way to pass an external service collection to the WebHostBuilder.

When this scenario is something which is desirable (I hope so :)), then let´s discuss where would be a appropriate place to add this feature.

What comes into my mind, are these three possibilities:

When we agree on an appropriate place to add this, I would be happy to supply a PR.

glennc commented 6 years ago

Either of those could work, but the bigger issue would be that the webhostbuilder doesn't do tryadd today.

How does this work if someone adds a service to the collection that the WebHostBuilder then wants to create and add, like IHostingEnvironment. This seems like a much bigger ask, namely "allow WebHostBuilder to know that another builder has already initialized all the services it needs and do nothing". No?

That leaves out potential problems with multiple builds of the service provider and whether or not it's possible to get all parts of all modules to use the same instance.

khellang commented 6 years ago

I think you could almost achieve some of this by implementing and registering an instance of IServiceProviderFactory<IServiceCollection> in the WebHostBuilder.

Instead of returning back the services passed into the CreateBuilder method, you could return an instance passed into its constructor, potentially merging them in some way. If you don't copy over registrations from the hosting services (passed in), you need to make sure all required services are in place for the web host (and app) to work.

davidfowl commented 6 years ago

I think you could almost achieve some of this by implementing and registering an instance of IServiceProviderFactory in the WebHostBuilder.

Yes, that is the recommended way to go about this.

eisendle commented 6 years ago

IServiceProviderFactory will not solve the problem, because the problem is more general. In terms of dependency injection, applications have to be build around AspNetCore in the designated extension points IServiceProviderFactory or StartUp.ConfigureServices. This feels wrong to me, because dependency injection should be configurable "outside" of WebHostBuilder.

The problem is, although IServiceProviderFactory provides a way to customize how the IServiceProvider is created, WebHostBuilder still controls when IServiceProvider is created.

This is particular problematic when using other frameworks like e.g Orleans. They mimic WebHostBuilder and use the same workflow. I´have created a gist to show how akward and cumbersome it is to use AspNetCore and Orleans together: here I came up with no other solution to make AspNetCore and Orleans to share the same IServiceProvider.

One possible solution in my opinon would be, to make the build process composable and give an external entity control over IServiceProvider creation. This BuildComposer would first ask all composables to register the services and create the service provider and give it to the composables. In this scenario WebHostBuilder and SiloHostBuilder would register to the BuildComposer.

I know this would break the current build process for webhostbuilder and there are multiple open points like duplicate registrations @glennc mentioned. However this would make it much easier to use multiple frameworks.

davidfowl commented 6 years ago

I've written why it's physically impossible to provide a build IServiceProvider, it is a mismatch, it'll never work with the WebHostBuilder. it owns the container and that will not change, the model is the model and isn't changing, we can make a new model that isn't what the WebHostBuilder is (nor the HostBuilder).

I've written about this in detail on several issues:

https://github.com/aspnet/Hosting/issues/1060 https://github.com/aspnet/Hosting/issues/1309 https://github.com/aspnet/Hosting/issues/550

aspnet-hello commented 6 years ago

We periodically close 'discussion' issues that have not been updated in a long period of time.

We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.