简体   繁体   中英

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?

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

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 . ie IOptions<TOption> .

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

services.AddSingleton<IEncrypter, Encrypter>();

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 )

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.

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM