Я работаю на фабрике, которая должна возвращать обобщенную c реализацию интерфейса в соответствии с типом.
Мой основной вопрос иллюстрируется
Почему эти typeof (TException)! = Exception.GetType ()? Соответственно, что я должен изменить, чтобы иметь правильный тип для TException?
Приведенный выше код приводит к исключению InvalidCast, потому что он пытается привести к IDocumedisExceptionHandler<DocumedisException>
вместо IDocumedisExceptionHandler<FhirParsingException>
Реализация фабрики:
internal class DocumedisExceptionHandlerFactory : IDocumedisExceptionHandlerFactory
{
private readonly IDictionary<Type, object> _exceptionHandlers = new ConcurrentDictionary<Type, object>();
public void RegisterExceptionHandler<TException>(IDocumedisExceptionHandler<TException> exceptionHandler)
where TException : DocumedisException
{
_exceptionHandlers.Add(typeof(TException), exceptionHandler);
}
public IDocumedisExceptionHandler<TException> GetDocumedisExceptionHandler<TException>(TException exception)
where TException : DocumedisException
{
_exceptionHandlers.TryGetValue(exception.GetType(), out var exceptionHandler);
return (IDocumedisExceptionHandler<TException>) exceptionHandler;
}
}
Дополнительный вопрос: есть ли лучший способ, чем использовать object
в качестве значения словаря?
Регистрация обработчика при запуске:
var exceptionHandlerFactory = app.ApplicationServices.GetService<IDocumedisExceptionHandlerFactory>();
exceptionHandlerFactory.RegisterExceptionHandler(new FhirParsingExceptionHandler());
Где FhirParsingExceptionHandler
реализует IDocumedisExceptionHandler
internal class FhirParsingExceptionHandler : IDocumedisExceptionHandler<FhirParsingException>
{
public void HandleException(FhirParsingException exception, out HttpStatusCode httpStatusCode, out OperationOutcome.IssueType issueType, out string message)
{
httpStatusCode = HttpStatusCode.BadRequest;
issueType = OperationOutcome.IssueType.Invalid;
message = exception.Message;
}
}
Определение обработчика (где TException
является контравариантным):
public interface IDocumedisExceptionHandler<in TException>
where TException : DocumedisException
{
void HandleException(TException exception, out HttpStatusCode httpStatusCode, out OperationOutcome.IssueType issueType, out string message);
}
И FhirParsingException
расширяется DocumedisException
:
public class FhirParsingException : DocumedisException
{
[...]
}
Извлечение обработчика из промежуточного программного обеспечения:
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
if (ex is DocumedisException documedisException)
{
await HandleDocumedisExceptionAsync(context, documedisException);
}
else
{
throw;
}
}
}
private async Task HandleDocumedisExceptionAsync<TException>(HttpContext context, TException ex, MedicationAnalyzerErrorCode? errorCode = null)
where TException : DocumedisException
{
var exceptionHandler = _documedisExceptionHandlerFactory.GetDocumedisExceptionHandler(ex);
[...]
}