这个人花了我一段时间才能弄清楚,但它既有趣又充满挑战,并最终找到了可行的解决方案。
另外,我确实知道这可能不是您想要的。如果ASP提供了一些您可以在Startup类中注册的现成的东西,那会很好,我认为这是您正在寻找的东西。
如果外面有人知道这种功能,我希望有更好的解决方案!
这是我使用过的[TestMethod]
,可以放在MSTest [TestClass]
中
[TestMethod]
public void _58790281()
{
try
{
throw new IOException("Text IO Exception");
}
catch (Exception e)
{
PassExceptionToHandler(e);
}
}
private void PassExceptionToHandler(Exception ex)
{
Assembly assembly = Assembly.GetAssembly(typeof(IExceptionHandler<>));
List<Type> concreteTypes = assembly.GetTypes().Where(a => !a.IsInterface).ToList();
Type currentExceptionHandlerType = concreteTypes
.FirstOrDefault(a => a.GetInterfaces().Any(i =>
i.IsGenericType
&& i.GetGenericTypeDefinition() == typeof(IExceptionHandler<>)
&& i.GenericTypeArguments.Any(ii => ii == ex.GetType())));
MethodInfo exceptionHandlerMethod = currentExceptionHandlerType.GetMethod("HandleException");
var exceptionHanderInstance = Activator.CreateInstance(currentExceptionHandlerType);
exceptionHandlerMethod.Invoke(exceptionHanderInstance,new object[] { ex });
}
编辑:当然,您将需要隔离处理程序,以减少反射成本,也许将它们放置在自己的程序集中,或对其进行修改以从命名空间或其他内容中获取类型,以使它不会查看您的所有类型。主装配体。
EDIT_01:ASP.Net Core实际上确实提供了一些用于全局异常处理的配置,只是遇到了https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-3.0
,
您可以使用Scrutor库来扫描任何接口的所有实现的程序集,并在该库的帮助下自动注册它们。
例如:
services.Scan(scan => scan
.FromCallingAssembly()
.AddClasses(x=> x.AssignableTo(typeof(IOpenGeneric<>))) // Can close generic types
.AsImplementedInterfaces()
.WithScopedLifetime()
);
然后,您可以在中间件内部调用IServiceProvider
以获取所有已注册的实现,然后需要进行一些反射或动态调度才能执行所需异常处理程序的Handle
方法。
此外,您还必须以某种方式保留该异常处理程序的顺序。让我解释一下我的意思。例如,对于SqlException
,您必须执行SqlExceptionHandler
(更具体),而不是ExceptionHandler
。您将如何找出哪个处理程序更具体?
所有这些当然可以完成。但是,我认为这会 引入不必要的复杂性 给您的代码库。
我认为最好创建一个基本异常Middleware。
然后是多个派生的中间件。正如msdn中所述,好事是:
在中间件组件中添加中间件组件的顺序
Startup.Configure方法定义中间件的顺序
组件是根据请求调用的。
如您所见,采用这种方法,订单问题将自动得到解决。
以下是一些示例代码:
public abstract class BaseExceptionHandlingMiddleware
{
private readonly RequestDelegate _nextMiddlewareRequestDelegate;
public ExceptionHandlingMiddleware(RequestDelegate nextMiddlewareRequestDelegate)
{
_nextMiddlewareRequestDelegate = nextMiddlewareRequestDelegate;
}
public async Task Invoke(HttpContext context)
{
try
{
await _nextMiddlewareRequestDelegate(context);
}
catch (Exception exception)
{
await HandleExceptionAsync(context,exception);
}
}
private static Task HandleExceptionAsync(HttpContext context,Exception exception)
{
var errorDescription = exception.Message;
var result = JsonConvert.SerializeObject(new { error = errorDescription });
context.Response.ContentType = MediaTypeNames.Application.Json;
context.Response.StatusCode = (int)DetermineStatusCode(exception);
return context.Response.WriteAsync(result);
}
protected virtual HttpStatusCode DetermineStatusCode(Exception exception);
}
创建SqlExceptionHandlinMiddleware
,IOExceptionHandlinMiddleware
,GeneralExceptionHandlinMiddleware
,然后覆盖DetermineStatusCode
。
然后注册它们:
builder.UseMiddleware<SqlExceptionHandlinMiddleware>();
builder.UseMiddleware<IOExceptionHandlinMiddleware>();
builder.UseMiddleware<GeneralExceptionHandlinMiddleware>();
本文链接:https://www.f2er.com/3128635.html