Injecting IOptions to static class


Injecting IOptions<> to static class



I would like to keep the class as static. Is there any workaround to inject IOptions<EncryptionSettings> without modifying the access modifier?


IOptions<EncryptionSettings>


public static class Encrypter
{
private static readonly Encoding encoding = Encoding.UTF8;

private static readonly EncryptionSettings _encryptionSettings;

public static Encrypter(IOptions<EncryptionSettings> encryptionSettings)
{
_encryptionSettings = encryptionSettings.Value;
}

public static string Encrypt(string plainText)
{
(...)
}

public static string Decrypt(string plainText)
{
(...)
}

static byte HmacSHA256(String data)
{
(...)
}
}



'Encrypter.Encrypter(IOptions)':
access modifiers are not allowed on static constructors



'Encrypter.Encrypter(IOptions)':
a static constructor must be parameterless





why is it a static class? could you use a singleton lifetime in your container?
– Daniel A. White
Jun 30 at 17:34





gist.github.com/doncadavona/fd493b6ced456371da8879c22bb1c263 IOptions contain the key
– Damian
Jun 30 at 17:46





3 Answers
3



Poor design choice making that class static.



And you are experiencing the challenges associated with trying to use it with dependency injection. Static and DI do not mix well and should be avoided as much as possible.



Encapsulate the desired functionality behind an abstraction.


public interface IEncrypter {
string Encrypt(string plainText);
string Decrypt(string plainText);
}



and implement it


public class Encrypter : IEncrypter {
private static readonly Encoding encoding = Encoding.UTF8;
private readonly EncryptionSettings _encryptionSettings;

public Encrypter(IOptions<EncryptionSettings> encryptionSettings) {
_encryptionSettings = encryptionSettings.Value;
}

public string Encrypt(string plainText) {
//(...)
}

public string Decrypt(string plainText) {
//(...)
}

static byte HmacSHA256(String data) {
//(...)
}
}



This would now allow the encryption abstraction IEncrypter to be injected as needed along with its own dependencies . i.e IOptions<TOption>.


IEncrypter


IOptions<TOption>



If meant to be the only encryption service then register it as a singleton at startup


services.AddSingleton<IEncrypter, Encrypter>();





This looks nice. Thank you for your time!
– Damian
Jun 30 at 18:47



No this isn't possible. First of all, your static constructor can't have access modifiers (public) or parameters at all. A static constructor is called by the CLR the first time you access the static class. (See msdn)


public



Since this is called by the CLR and can't ever be called by you, it also can't be called by your DI framework. You should use a singleton and register it as a service like any other instanced class.





I was playing with the code and forgot to remove "public" access modifier before pasting the code here.
– Damian
Jun 30 at 17:54



It violates DI, but provided your DI is configured before your Encrypter class is ever used then you could use a static reference to your DI container:


Encrypter


public static class Encrypter
{
private static readonly EncryptionSettings _encryptionSettings;

static Encrypter()
{
if( IoC.Instance == null ) throw new InvalidOperationException( "IoC must be initialized before static members of Encrypter are used." );
_encryptionSettings = IoC.Instance.GetService<IOptions<EncryptionSettings>>();
}
}



...but please don't do this.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

List of Kim Possible characters

Audio Livestreaming with Python & Flask

NSwag: Generate C# Client from multiple Versions of an API