I've been using dependency injection for about 6 months now and sometimes there is a situation I don't know how to handle in an elegant way.
Say I want a class for storing all my app settings in. This class is only initialized at beginning.
Please let me know how idea 1 can be executed (as I think this is the classic way) and if idea 2 is a valid pattern or if there is a better alternative.
Idea 1:
make this class static as its variables are only initialized and after that everything stays read-only. The problem with this is that I do not know where to initialize variables of this class. To initialize one of the variables a password needs to be decrypted which requires the use of IEncryption
interface.
I would like to initialize these static variables before the main program actually start (so preferably in Startup.cs
). I can't do that because I can't get the implementation of IEncryption in the DI container class, or at least I don't know an elegant way to get it. How should this be done with a static class? should I make another "middleware" between Startup and actual program logic where I can initialize static variables?
If I'm not mistaken simple data only classes that are application wide are ok to be static object even when using DI pattern
Idea 2:
Now I don't know if this has a name or if it's ever used. It's just something I came up with and it seems like a good solution for me but there might be an alternative I don't know of that makes it useless.
What if I instead of making this class static I make it as a normal class and initialize all static variables inside class constructor.
So something like this:
public ClientData(IConfiguration configuration, IEncryption encryption)
{
var section = configuration.GetSection(nameof(ClientData));
EdgeUrl = section.GetValue<string>(nameof(EdgeUrl));
EdgeAuthUrl = section.GetValue<string>(nameof(EdgeAuthUrl));
Username = section.GetValue<string>(nameof(Username));
Password = encryption.Decrypt(section.GetValue<string>(nameof(Password)));
OrganizationKey = section.GetValue<string>(nameof(OrganizationKey));
}
public string EdgeUrl { get; }
public string EdgeAuthUrl { get; }
public string Username { get; }
public string Password { get; }
public string OrganizationKey { get; }
I then inject IEncryption through the constructor.
CodePudding user response:
I would definitely recommend the second approach, except that you should keep the properties as regular properties, and no static fields or properties.
You should be able to register this in the DI container as a 'singleton'. This ensures only one instance is created. So it will be kind of static in the sense that there 'is only one', but only in the context of the DI container rather than for the whole process. This allows more flexibility, for example if you want to different parts of the application to use different configurations.
This will require the class to be injected into each place it is used. Luckily the DI container should make that trivial.