Внедрение IOptions <> в статический класс - PullRequest
0 голосов
/ 30 июня 2018

Я хотел бы сохранить класс как статический. Есть ли обходной путь для ввода 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) ': не разрешены модификаторы доступа для статических конструкторов

Encrypter.Encrypter (IOptions) ': статический конструктор должен быть без параметров

Ответы [ 3 ]

0 голосов
/ 30 июня 2018

Это нарушает DI, но при условии, что ваш DI настроен до того, как ваш класс Encrypter когда-либо используется, вы можете использовать статическую ссылку на ваш контейнер 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>>();
    }
}

... но, пожалуйста, не делайте этого.

0 голосов
/ 30 июня 2018

Плохой выбор дизайна делает этот класс статичным.

И вы испытываете трудности, связанные с попыткой использовать его с внедрением зависимости. Static и 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>();
0 голосов
/ 30 июня 2018

Нет, это невозможно. Прежде всего, ваш статический конструктор вообще не может иметь модификаторов доступа (public) или параметров. Статический конструктор вызывается CLR при первом обращении к статическому классу. ( См. MSDN )

Так как это вызывается CLR и никогда не может быть вызвано вами, оно также не может быть вызвано вашей структурой DI. Вы должны использовать singleton и зарегистрировать его как сервис, как и любой другой экземплярный класс.

...