Внедрение зависимостей без контроллера - PullRequest
0 голосов
/ 11 мая 2018

Я хочу сделать активацию электронной почты в моем проекте. Я работаю с Entity Framework для соединений с базой данных на уровне хранилища, и Сервисы используют эти слои.

Я хочу создать ключ и вставить в базу данных с Entity Framework и службой Dependency Injection без неконтроллера.

Слои репозитория

public void Insert(T entity)
{
    if (entity == null)
    {
        throw new ArgumentNullException("entity");
    }

    _entities.Add(entity);
    SaveChanges();
}

ActivationService

public void Insert(EmailValid entity)
{
    _repositoryBase.Insert(entity);
}

Класс не контроллера

public class EmailActivaitonKey
{
    private readonly IActivationService _activationService;

    public EmailActivaitonKey()
    {
        this._activationService = Startup.ActivationService;
    }

    public string ActivationKey(string email)
    {
        string guid = Guid.NewGuid().ToString();
        while (_activationService.GetByFilter(i => i.ActivationKey == guid) != null)
        {
            guid = Guid.NewGuid().ToString();
        }

        string key = email + ":OSK:" + DateTime.Now + ":OSK:" + guid;
        EmailValid emailValid = new EmailValid
        {
            Email = email,
            Time = DateTime.Today,
            ActivationKey = key
        };

        _activationService.Insert(emailValid);
        return new Helpers.AESEncryption().EncryptText(key);
    }
}

в другом классе объявляет EmailActivationKey

MailMessage mailMessage = new MailMessage
{
    From = new MailAddress("***@***.***"),
    Body = "Crypto Box Activation",
    Subject = $"<a href='/Email/Activation?key={new EmailActivaitonKey().ActivationKey(email)}'><h1>Click For Activation<h1><a>",
    To = { email }
};

при запуске:

public static IActivationService ActivationService;

//then 
services.AddScoped<IActivationService, ActivationService>();
ActivationService = services.BuildServiceProvider().GetService<IActivationService>();

Я посмотрел на этот вопрос и на этот вопрос , но я не получил никаких результатов.

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Это примерно полная противоположность внедрению зависимости (обратите внимание, что вы не объявляете зависимость, а фактически скрываете ее).Это называется анти-паттерном сервисного локатора:

public EmailActivaitonKey()
{
    this._activationService = Startup.ActivationService;
}

Если вы хотите использовать Dependency Injection, это должно выглядеть следующим образом (опечатка исправлена):

public EmailActivationKey(IActivationService activationService)
{
    _activationService = activationService;
}

Затем удалитеполностью это и поле ActivationService:

ActivationService = services.BuildServiceProvider().GetService<IActivationService>();

Кроме того, это очень странно:

string guid = Guid.NewGuid().ToString();
while (_activationService.GetByFilter(i => i.ActivationKey == guid) != null)
{
    guid = Guid.NewGuid().ToString();
}

Я не уверен, почему вы ожидаете найти дубликаты GUID,поскольку именно поэтому они существуют.

0 голосов
/ 11 мая 2018

Как и в других ответах, вы можете просто передать класс в качестве параметра классу, не являющемуся контроллером, и инжектор зависимостей передаст его вам.

public class EmailActivaitonKey
{
    private readonly IActivationService _activationService;

    public EmailActivaitonKey(IActivationService service)
    {
        this._activationService = service;
    }
    ....
}

Если вам нужен только один экземпляр сервиса для всего приложения, вы добавляете сервис как Singleton в ConfigureServices

services.AddSingleton<IActivationService, ActivationService>();

Вам не нужно создавать статическую переменную для экземпляра, так как объект 'ServiceProvider', т.е. объект services, будет держать его для вас.

EDIT Вы можете передать класс EmailActivationKey в качестве параметра другому классу, и DI внедрит его для вас, например,

public class EmailClass
{
    private readonly EmailActivationKey _key;

    public EmailClass(EmailActivationKey key)
    {
        _key = key;
    }
}

Если вы хотите новый каждый раз, измените services обратный вызов на scoped, например

services.AddScoped<EmailActivationKey>();

DI создаст для вас новый запрос для каждого запроса.

...