将 IOptions<> 注入静态 class

Injecting IOptions<> to static class

我想将 class 保持为静态。是否有任何解决方法可以在不修改访问修饰符的情况下注入 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

不,这不可能。首先,您的静态构造函数根本不能有访问修饰符(public)或参数。第一次访问静态 class 时,CLR 会调用静态构造函数。 (See msdn)

由于这是由 CLR 调用的,您永远无法调用它,因此您的 DI 框架也无法调用它。您应该使用单例并将其注册为任何其他实例化的服务 class.

它违反了 DI,但如果你的 DI 在你的 Encrypter class 被使用之前配置,那么你可以使用对你的 DI 容器的静态引用:

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>>();
    }
}

...但请不要这样做。

糟糕的设计选择使 class 静态。

并且您正在经历与尝试将其与依赖注入一起使用相关的挑战。静电和 DI 不能很好地混合,应尽可能避免。

将所需的功能封装在抽象背后。

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

并实施

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) {
        //(...)
    }
}

现在这将允许加密抽象 IEncrypter 根据需要连同它自己的依赖项一起注入。即 IOptions<TOption>.

如果打算成为唯一的加密服务,则在启动时将其注册为单例

services.AddSingleton<IEncrypter, Encrypter>();