Asp.net Core获取依赖注入的实例

时间:2017-10-25 00:04:06

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

我在Startup.cs中添加了一个全局错误处理程序过滤器,如下所示:

services.AddMvc(o =>
{
    o.Filters.Add(new GlobalExceptionFilter());
});

但是,我需要传递我的电子邮件服务,该服务也正在注入。如何从过滤器中的这些服务中检索它?

public class GlobalExceptionFilter : IExceptionFilter
{
    private readonly IEmailService _emailService;

    public GlobalExceptionFilter()
    {
    }

    public void OnException(ExceptionContext context)
    {

    }
}

我使用能够使用DependencyResolver类在MVC5中执行此操作。有没有办法在核心实现这一目标?或者有没有办法让我在Startup中强制实例化服务,这样我就可以将它作为构造函数的一部分传递?

我尝试在服务中查找,然后查看ImplementationInstance,但此时它为null,因此我无法从中显示它。另请注意,我的EmailService需要IOptions<Settings>参数,以便它可以获得所需的电子邮件设置。

2 个答案:

答案 0 :(得分:4)

您可以使用构造函数注入。

public class GlobalExceptionFilter : IExceptionFilter
{
    private readonly IEmailService emailService;
    public GlobalExceptionFilter(IEmailService emailService)
    {
        this.emailService = emailService;
    }
    public void OnException(ExceptionContext context)
    {
       //do something with this.emailService
    }
}

但是你必须改变你在ConfigureServices方法中注册全局过滤器的方式。您应该使用带有Type

Add重载
services.AddMvc(o =>
{
    o.Filters.Add(typeof(GlobalExceptionFilter));
});

另一个选择是,通过调用OnException上的GetService方法,明确解决HttpContext.RequestServices方法中的依赖关系。

public void OnException(ExceptionContext context)
{
    var emailService = context.HttpContext.RequestServices.GetService<IEmailService>();
    // use emailService
} 

但是你应该对第一种方法没问题。让框架为您解决它并注入您的构造函数而不是您尝试执行它。

答案 1 :(得分:1)

我认为Global Exception Handler的最佳实践实际上是为它创建一个自定义中间件步骤。来自documentation

  

异常过滤器适用于捕获MVC操作中发生的异常,但它们不像错误处理中间件那样灵活。首选中间件用于一般情况,并仅在需要根据选择的MVC操作进行不同的错误处理时使用过滤器。

然后在ConfigureServices方法中注册类:

services.AddTransient<IEmailService, EmailService>();

然后在您的Configure方法中,注册您的客户全局异常处理程序。您将希望这是您在Configure方法中做的第一件事,因此您可以在其他中间件中捕获跟随它的任何异常。

app.UseMiddleware<MyGlobalExceptionHandler>();

您注册的任何服务都可用于您的中间件构造函数,可能如下所示:

public sealed class MyGlobalExceptionHandler
{
    private readonly RequestDelegate _next;
    private readonly IEmailService _emailService;

    public NlogExceptionHandler(
        RequestDelegate next,
        IEmailService emailService)
    {
        _next = next;
        _emailService = emailService;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {

            await _next(context);
        }
        catch (Exception ex)
        {
            try
            {
                _emailService.SendEmail(ex.ToString());
            }
            catch (Exception ex2)
            {
                //Its good practice to have a second catch block for simple logging in case the email fails too
            }

            throw;
        }
    }
}