. net} core method for reading configuration files

Time:2022-5-18

Configuration file is the most basic and indispensable part of each project, such as common configurations such as database connection and middleware properties.

The main content of today’s article is in Net core project how to read configuration files and use them.

Prepare in advance

appsettings. JSON file

{
  "User": {
	"Username": "Zhao Yi",
	"userAge": 18
  }
}

Corresponding entity model


public class UserOption
{
	public string userName { get; set; }
	public int userAge { get; set; }
}

General read

1. Register

Registering in the startup class mainly uses the configure method:


services.Configure<UserOption>(Configuration.GetSection("User"));

2. Inject and read in the controller

public class HomeController : ControllerBase
{
    private readonly UserOption user;

    public HomeController(IOptions<UserOption> userOptions)
    {
        user = userOptions.Value;
    }

    [HttpGet]
    public string Get()
    {
        Return $"Name: {user. Username}, age: {user. Userage}";
    }
}

Output result:Name: Zhao Yi, age: 18

Nested read

We are interested in Appsettings JSON file to make a small change, add a child nodechild

{
  "User": {
	"Username": "Zhao Yi",
	"userAge": 18,
	"child": {
	  "Username": "Zhao Yi's cub",
	  "userAge": 2
	}
  }
}

Make a small change to the registered code:


services.Configure<UserOption>(Configuration.GetSection("User:child"));

Output result:Name: Zhao Yi's cub, age: 2

Read by instance

At this time, the requirements change again and need to be read at the same timeUserAndchildFor node data, let’s try the following method to see if it is feasible:

//Register
services.Configure<UserOption>(Configuration.GetSection("User"));
services.Configure<UserOption>(Configuration.GetSection("User:child"));
//Controller
public class HomeController : ControllerBase
{
    private readonly UserOption user;
    private readonly UserOption child;

    public HomeController(IOptions<UserOption> userOptions, IOptions<UserOption> childOptions)
    {
        user = userOptions.Value;
        child = childOptions.Value;
    }

    [HttpGet]
    public string Get()
    {
        Return $"Name: {user. Username}, age: {user. Userage} \ R \ nname: {child. Username}, age: {child. Userage}";
    }
}

Obviously, the output results can not meet our needs:

Name: Zhao Yi's cub, age: 2
Name: Zhao Yi's cub, age: 2

Some small partners will certainly say that a child node field is added to the entity model. This is certainly no problem, but it is no different from the conventional reading method.

What I want to say here is to read by instance and introduceConfigureAnother overloaded method, different from the previous one, has one more parametername


public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config) where TOptions : class;

Now let’s re register:


services.Configure<UserOption>("father", Configuration.GetSection("User"));
services.Configure<UserOption>("son", Configuration.GetSection("User:child"));

Injection in the controller constructor also introduces a new interface object:IOptionsMonitor

public class HomeController : ControllerBase
{
    private readonly UserOption user;
    private readonly UserOption child;

    public HomeController(IOptionsMonitor<UserOption> userOptions, IOptionsMonitor<UserOption> childOptions)
    {
        user = userOptions.Get("father");
        child = childOptions.Get("son");
    }

    [HttpGet]
    public string Get()
    {
        Return $"Name: {user. Username}, age: {user. Userage} \ R \ nname: {child. Username}, age: {child. Userage}";
    }

Output result:

Name: Zhao Yi, age: 18
Name: Zhao Yi's cub, age: 2

In fact, there is another interface object that can achieve this effect:IOptionsSnapshot, thatIOptionsMonitorAndIOptionsSnapshotWhat’s the difference? Please keep looking down.

Differences between ioptionsmonitor and ioptionssnapshot

Let’s take a look at Microsoft’s official comments:

IOptionsMonitor

//
//Summary:
//     Used for notifications when TOptions instances change.
//
//Type parameter:
//   TOptions:
//     The options type.
public interface IOptionsMonitor<out TOptions>
{
    //
    //Summary:
    //     Returns the current TOptions instance with the Microsoft.Extensions.Options.Options.DefaultName.
    TOptions CurrentValue { get; }

    //
    //Summary:
    //     Returns a configured TOptions instance with the given name.
    TOptions Get(string name);
    //
    //Summary:
    //     Registers a listener to be called whenever a named TOptions changes.
    //
    //Parameters:
    //   listener:
    //     The action to be invoked when TOptions has changed.
    //
    //Return result:
    //     An System.IDisposable which should be disposed to stop listening for changes.
    IDisposable OnChange(Action<TOptions, string> listener);
}

IOptionsSnapshot

//
//Summary:
//     Used to access the value of TOptions for the lifetime of a request.
//
//Type parameter:
//   TOptions:
//     Options type.
public interface IOptionsSnapshot<out TOptions> : IOptions<TOptions> where TOptions : class, new()
{
    //
    //Summary:
    //     Returns a configured TOptions instance with the given name.
    TOptions Get(string name);
}

Literally,IOptionsMonitorIt is recommended to be used in the scenario where notification is required after the configuration information is changed, so there are more than oneOnChangeMethods of; andIOptionsSnapshotIt’s a little difficult to understand that it is used to access the configuration within the life cycle of the request. Let’s verify it with code.

Lifecycle of ioptionsmonitor and ioptionsnapshot

Let’s make a small modification to the entity model, add a guid field and give the default value:


public class UserOption
{
    public string userName { get; set; }
    public int userAge { get; set; }

    public Guid guid { get; set; } = Guid.NewGuid();
}

We run the program again:

Father - Name: Zhao Yi, age: 19, No.: e0d71f47-e8f1-4a6d-875e-2074c985f4a0 
Son - Name: Zhao Yi's cub, age: 3, number: d865151b-f9bf-4eff-bb4e-8ab6dc61160c

Then keep refreshing the page and you will find that,fatherNo number has occurred for the number, andsonThe number of is changed every time it is refreshed. Is this more like the three modes we use when registering:


services.AddScoped();
services.AddTransient();
services.AddSingleton()

amongfathersimilarAddSingletonsonThen similarAddScopedAndAddTransient

You can call multiple times in the same methodchildOptions.Get("son")have a looksonSimilar in the endAddScopedstillAddTransient

Onchange calling mode of ioptionsmonitor


userOptions.OnChange((user,name)=> { Console.WriteLine(user.userName +"-"+ name); });

No file configuration

No file configuration means that it does not need to be configured as a static file. The relevant information does not need to be modified after being configured once. We can use the way of file free configuration, such as those we are familiar withAddCorsCross domain configuration


services.AddCors(op => {
	op.AddPolicy(CorsName, set => {
		set.SetIsOriginAllowed(origin => true).AllowAnyHeader().AllowAnyMethod().AllowCredentials();
            });
        });

We make the following changes to the previous registration method:

services.Configure<UserOption>(c =>
{
	c. Username = "Qian Er";
	c.userAge = 60;
});

The controller injection adopts the conventional injection method, and the final output result is:Name: Qian Er, age: 60

Share a source code view website:https://source.dot.net/

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.