简体   繁体   中英

Why is typeof(T) != instance.getType()?

I'm working on a factory which shall return a generic implementation of an interface according to a type.

My main question is being illustrated by
在此处输入图像描述 Why are these typeof(TException).= exception?GetType(), Respectively? what do I have to change to have the correct type for TException?

The above code results in a InvalidCast exception because it tries to cast to IDocumedisExceptionHandler<DocumedisException> instead of IDocumedisExceptionHandler<FhirParsingException>

Factory implementation:

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;
    }
}

Side question: Would there be a better way then using object as dictionary value?

Registration of the handler in startup:

var exceptionHandlerFactory = app.ApplicationServices.GetService<IDocumedisExceptionHandlerFactory>();
exceptionHandlerFactory.RegisterExceptionHandler(new FhirParsingExceptionHandler());

Where FhirParsingExceptionHandler implements 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;
    }
}

Handler definition (where TException is contravariant):

public interface IDocumedisExceptionHandler<in TException>
    where TException : DocumedisException
{
    void HandleException(TException exception, out HttpStatusCode httpStatusCode, out OperationOutcome.IssueType issueType, out string message);
}

And FhirParsingException extends DocumedisException :

public class FhirParsingException : DocumedisException
{
   [...]
}

Retrieval of the handler from the middleware:

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);
   [...]
}

typeof(TException) gives you the compile time type of exception . exception.GetType() gives you the runtime type of exception . These two need not be the same at all, the only guarantee the compiler makes is that the runtime type of exception will be assignable to a TException variable.

Consider the following:

class Animal { }
class Turtle: Animal { }
bool CheckTypes<T>(T animal) where T: Animal 
{
     return typeof(T) == animal.GetType();
}

And now you have:

Animal animal = new Turtle();
Feed(animal);

Rest assured, CheckTypes will return false ; the type of the generic type argument is Animal but the runtime type of animal is really Turtle .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM