dotnet core console application IOptions configuration
So, I’m losing faith in my google skills, there didn’t seem to be a one stop shop that I could find to give information on setting up a .net core console application with a IServiceProvider
and utilizing IOptions
… so that brings us here.
In the process of needing configuration for the first time in a console app — crazy I know. The project is currently using AutoFac as its IOC container — though having to look into .netcore’s built in IOC container, I may want to switch to it!
The basis of wanting to utilize configuration for the app for the first time is utilizing differing endpoints for external resources, depending on the environment. These configuration values would be loaded at the applications entry point (or thereabouts) and would need to be accessed deep within the internals of the app, very likely not even within the same project.
How can I do this without having to set some static member somewhere in which everything has access? That led me to find IOptions
(Doc) — T being a configuration class. IOptions
allows for the injection of configuration values into a class, this is exactly what’s needed, and avoids the thing I was worried about having to either pass a configuration collection all over the call stack, or using a static member somewhere in the app.
The first thing we need to do in the console app, is to create a configuration file.
appsettings.json :
1 |
|
and load it in the entry point of our console app
Program.cs :
1 |
|
Ok! File loaded, it currently does nothing! Next, we’ll want to load an environment specific json file, but in order to do that, we’ll need a concept of an environment. Seems like the environment is often controlled via an “environment variable” (no relation?). There are various ways to set environment variables, depending on OS. Some of those methods include:
I’m going to set a new environment variable for a seemingly standard ASPNETCORE_ENVIRONMENT
to “local”. Another sample environment we’ll use is “test”.
Now we can go about creating a few new configuration files for the other environments.
appsettings.local.json :
1 |
|
appsettings.test.json
1 |
|
Now we have a “base” configuration appsettings.json, and environment specific configurations appsettings.local.json and appsettings.test.json. This coupled with our new environment variable should allow us to start working with some configuration in a meaningful way (pretty soon).
For now, let’s take a look at what loading the different environment configuration files looks like. From our original example of Program.cs
1 |
|
Let’s make a few updates:
1 |
|
In this above, you can see we’re loading into env the value stored in the environment variable ASPNETCORE_ENVIRONMENT, when/if this variable isn’t available we (currently) throw an exception. We then print the environment variable value we loaded, and finally load the appropriate appsettings.{env}.json. You can see the loaded environment changes depending on the value of the environment variable ASPNETCORE_ENVIRONMENT.
Now that we’re successfully loading configuration files based on an environment variable, let’s get into some IOptions
First thing we’ll need is a configuration class, we’ll do something nice and simple like environment specific configuration for a API endpoint:
ApiConfig.cs
1 |
|
In the above we just have a class defined, and we would create json to represent those classes in each of our environment configuration files.
appsettings.local.json
1 |
|
appsettings.test.json
1 |
|
We now have enough “stuff” in place that we can load something into an IOptions
— our ApiConfig, or IOptions<ApiConfig>
.
We’ll make another change to our Program ctor:
1 |
|
A few new things above:
- serviceCollection — where we register our services
- ServiceProvider — where we “get” our registered services.
We can now “resolve” our registered components as per the normal dotnetcore resolver, and our new IOptions
can be used like so:
SomeClass.cs
1 |
|
The environment configuration loaded will determine which “instance” of ApiConfig
we inject into SomeClass.
One last hiccup on my end, is I’m actually using AutoFac, and not the .net core IOC container . Due to this all my resolutions are occurring through AutoFac, while my IOptions
are being registered through .net core’s IOC container.
This is another pretty simple change (though it at least took me a while to figure it out). I ended up throwing together a new helper method that takes in my IServiceProvider, as well as my ContainerBuilder (from AutoFac registration). The helper method looks like:
1 |
|
and can be called directly from our normal composition root/entry point that puts together the AutoFac container.
dotnet core console application IOptions configuration
https://blog.kritner.com/2018/09/14/dotnet-core-console-application-IOptions-T-configuration/