"Microsoft.Extensions.DependencyInjection"
List of "environments"
Production
Uat
Qa
DevShared
LocalDev
With DotNet (Framework/Classic) 4.6 or above (aka, "in the past", I used "Unity" with xml configuration. https://blogs.msdn.microsoft.com/miah/2009/04/03/testing-your-unity-xml-configuration/
(In the past before Dot Net core when using "Unity" IoC/DI)...When I had a need to have a concrete specific to an environment, I would tweak the concrete on the .xml. For instance, let's say my webApi needed authentication in production, uat, qa and dev-shared. but in dev-local, I do not want to deal with authentication all the time as I developed the webApi, I would have 2 concretes.
IAuthorizer
MyRealAuthorizer : IAuthorizer
MyDevLetEverythingThroughAuthorizer : IAuthorizer
and I would "register" one of them .. using xml.
My build process would alter the unity.xml (unity.config to be precise) and change out (via xml-update-tasks in msbuild)
MyDevLetEverythingThroughAuthorizer
to
MyRealAuthorizer
.
.....
Java Spring has "annotation" based:
import org.springframework.context.annotation.Profile;
@Profile("localdev")
public class MyDevLetEverythingThroughAuthorizer implements IAuthorizer {
@Profile("!localdev")
public class MyRealAuthorizer implements IAuthorizer {
But that does not honor the "Composite Root" pattern : (Mark Seeman http://blog.ploeh.dk/2011/07/28/CompositionRoot/ )
.......
So now I'm entering the world of DotNetCore. Everything has been going smooth. But I finally hit a situation where I need a dev-friendly concrete vs a non-dev "real" concretes.
Xml isn't available (to my best knowledge) with "Microsoft.Extensions.DependencyInjection".
I'm not sure of the best practice with DotNetCore in this situation.
I would prefer to honor the Composite Root pattern.
Basically, the below......but respecting the environments.
asp.net'ish
public void ConfigureServices(Microsoft.Extensions.DependencyInjection.IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
/* need this for "local-dev" */
services.AddScoped<IAuthorizer, MyDevLetEverythingThroughAuthorizer>();
/* need this for everything EXCEPT "local-dev" */
services.AddScoped<IAuthorizer, MyRealAuthorizer>();
}
(not asp.net) dot.net core'ish too
private static System.IServiceProvider BuildDi()
{
//setup our DI
IServiceProvider serviceProvider = new ServiceCollection()
.AddLogging()
/* need this for "local-dev" */
.AddSingleton<IAuthorizer, MyDevLetEverythingThroughAuthorizer>()
/* need this for everything EXCEPT "local-dev" */
.AddSingleton<IAuthorizer, MyRealAuthorizer>()
APPEND
This article and snipplet help me understand the "what is built in" portion a little better:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-2.2
Environments ASP.NET Core reads the environment variable ASPNETCORE_ENVIRONMENT at app startup and stores the value in IHostingEnvironment.EnvironmentName. You can set ASPNETCORE_ENVIRONMENT to any value, but three values are supported by the framework: Development, Staging, and Production. If ASPNETCORE_ENVIRONMENT isn't set, it defaults to Production.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc();
}
The
env.IsEnvironment("Staging_2") (akin to env.IsEnvironment("MyCustomValue") ) is the trick I guess.
APPEND:
This SOF question made it more clear for Asp.Net Core.
How to set aspnetcore_environment in publish file?
And ways you can set the environment variable without actually setting a (machine) environment variable!