[英]Drawbacks to Passing an Instance to ASP.NET Core Dependency Injection
[英]Asp.net Core get instance of Dependency Injection
我在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中做到这一点。 有没有办法做到这一点? 还是我有办法在启动中强制实例化服务,以便可以将其作为构造函数的一部分传递?
我尝试在服务中查找它,然后查看ImplementationInstance,但是此时它为null,所以我无法从那里获取它。 另外请记住,我的EmailService需要IOptions<Settings>
参数,以便它可以获取所需的电子邮件设置。
您可以使用构造函数注入。
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
方法中注册全局过滤器的方式。 您应该使用带有类型的Add
重载
services.AddMvc(o =>
{
o.Filters.Add(typeof(GlobalExceptionFilter));
});
另一个选择是,通过在HttpContext.RequestServices
上调用GetService
方法来显式解决OnException
方法内部的依赖关系。
using Microsoft.Extensions.DependencyInjection;
public void OnException(ExceptionContext context)
{
var emailService = context.HttpContext.RequestServices.GetService<IEmailService>();
// use emailService
}
但是第一种方法应该没问题。 让框架为您解决它,然后注入到构造函数中,而不用尝试这样做。
我认为,全局异常处理程序的最佳实践实际上是为其创建自定义中间件步骤。 从文档中
异常过滤器非常适合捕获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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.