Reputation: 780
I'm porting old .net v 4.5.1 project to the latest .net core. For dependency injection in old .net framework project Unity container is used where all service registrations are stored in web.config.
Global.asax:
UnityConfigurationSection section
= (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container, "unityContainer");
web.config:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container name="primaryUnityContainer">
<register type="ILogger" mapTo="Log4NetLogger"/>
The questing is: what are the best way in .net core 3 to configure the services in a configuration file outside the application, in appsettings.json for example so that different implementations could be registered for different environments.
Can built-in container be extended or it's better to use some 3rd party with this feature?
What are other approaches to have service implementations for specific environment?
Upvotes: 0
Views: 870
Reputation: 239290
You cannot configure services in ASP.NET Core outside of the application. Microsoft.Extensions.DependencyInjection
is entirely code-based, and while you can use other DI containers, they must be used and configured within the framework of the Microsoft.Extensions.DependencyInjection
facade.
That said, "environments" in ASP.NET Core are config-based. You don't compile the application multiple times for multiple different environments. Instead the you specify the environment on startup via either an environment variable like ASPNETCORE_ENVIRONMENT
or passing the environment at runtime such as via an CLI argument.
In either case, you can then branch in your code based on the environment value. There's actually three ways you can utilize the environment value to configure services differently per environment.
Inject IWebHostEnvironment
into Startup
private readonly IWebHostEnvironment _env;
public Startup(IWebHostEnvironment env)
{
_env = env;
}
Then, in ConfigureServices
:
if (_env.IsDevelopment())
{
...
}
if (_env.IsProduction())
{
...
}
if (_env.IsEnvironment("Foo"))
{
...
}
Use conventions-based naming with ConfigureServices
. In other words, you can define different Configure{EnvironmentName}Services
methods to your Startup
class:
public void ConfigureDevelopmentServices(IServiceCollection services)
{
...
}
public void ConfigureProductionServices(IServiceCollection services)
{
...
}
public void ConfigureFooServices(IServiceCollection services)
{
...
}
Use conventions-based naming with the Startup
class itself. You can actually define multiple Startup
classes like StartupDevelopment
, StartupProduction
, StartupFoo
, etc. The one catch is that you can then no longer use the generic UseStartup<T>
method when setting up your host in Program.cs
. Instead, you need the non-generic UseStartup
, which takes an assembly name string (as you won't know what startup class you actually need at compile-time):
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var assemblyName = typeof(Startup).GetTypeInfo().Assembly.FullName;
return WebHost.CreateDefaultBuilder(args)
.UseStartup(assemblyName);
}
Upvotes: 3
Reputation: 1783
you below type of configuration setting :
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
#if SOME_BUILD_FLAG_A
.AddJsonFile($"appsettings.flag_a.json", optional: true)
#else
.AddJsonFile($"appsettings.no_flag_a.json", optional: true)
#endif
.AddEnvironmentVariables();
this.configuration = builder.Build();
}
Upvotes: -1