【问题标题】:Dependency Injection without a Controller没有控制器的依赖注入
【发布时间】:2018-10-21 22:32:15
【问题描述】:

我想在我的项目中进行电子邮件激活。我使用实体框架与存储库层中的数据库连接,而服务使用这些层。

我想在没有非控制器的情况下使用实体框架和依赖注入服务创建密钥并插入数据库。

存储库层

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

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

激活服务

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

我查看了this questionthis one too,但没有得到任何结果。

【问题讨论】:

  • 如果你没有控制器,你希望这段代码如何运行?
  • 为什么人们认为依赖注入只适用于控制器,这是一个错误的假设。
  • 我知道依赖注入,但我无法调用函数,原因是类的构造函数有一个参数@JoeAudette
  • 构造函数是依赖注入的方式,它需要的任何参数也必须向DI注册

标签: c# asp.net-core dependency-injection


【解决方案1】:

正如其他答案所述,您可以将该类作为参数传递给非控制器类,依赖注入器将为您传递它。

public class EmailActivaitonKey
{
    private readonly IActivationService _activationService;

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

如果您只想要整个应用程序的一个服务实例,那么您可以将服务添加为 ConfigureServices 中的单例

services.AddSingleton<IActivationService, ActivationService>();

您无需为实例创建静态变量,因为“ServiceProvider”即services 对象将为您保存它。

编辑 您可以将 EmailActivationKey 类作为参数传递给另一个类,DI 会为您注入它,例如

public class EmailClass
{
    private readonly EmailActivationKey _key;

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

如果您每次都想要一个新的,则将 services 回调更改为 scoped e.g.

services.AddScoped<EmailActivationKey>();

DI 将为您的每个请求创建一个新的。

【讨论】:

  • 我如何调用这个 EmailActivaitonKey(IActivationService activationService) ? @SimplyGred
  • 我已经更新了我的答案,以展示如何将 EmailActivationKey 类注入到其他类中。
  • 谢谢我忘了注入它。
【解决方案2】:

这与依赖注入完全相反(请注意,您并没有声明依赖,而是有效地隐藏了它)。这被称为服务定位器反模式:

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

如果你想使用依赖注入,应该是这样的(错字已修复):

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,因为这正是它们存在的原因。

【讨论】:

  • Guid 有 5,316,911,983,139,663,491,615,228,241,121,400,000 (2^122) 个组合,我只是在检查一个微小的可能性:)
  • @OMansAK “从统计上看,如果你每秒计算 1000 个 GUID,仍然需要数万亿年才能得到一个副本”,这种可能性很小。不过,我想知道这个答案是否对您有所帮助。
  • @OMansAK 你没有,在 DI 应用程序中你没有使用 new 关键字。你想在哪里使用它?
  • Subject = $"

    点击激活"

    ,
  • @OMansAK 你真的需要阅读依赖注入。视图应该自行调用服务。从 Controller 传递 View 的所有数据
猜你喜欢
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多