samedi 21 septembre 2019

C# Resolve Concrete type from Generic Interface

I have the following scenario:

  1. I have several derived exceptions classes that implements a base exception
    //Base exception type
    public class SaberpsicologiaException : Exception
    {
    }

    //One of the derived exception class
    public class MovedPermanentlyException : SaberpsicologiaException
    {
        public string CannonicalUri { get; private set; }

        public MovedPermanentlyException(string cannonicalUri) 
            : base($"Moved permanently to {cannonicalUri}")
        {
            this.CannonicalUri = cannonicalUri;
        }
    } 


  1. For each exception class I want to implement an exceptionHandler that will return an ActionResult, which will implement a common interface:
    interface ISaberpsicologiaExceptionHandler<T>
        where T : SaberpsicologiaException
    {
        ActionResult Result(T exception);
    }

    public class MovedPermanentlyExceptionHandler 
        : ISaberpsicologiaExceptionHandler<MovedPermanentlyException>
    {
        public ActionResult Result(MovedPermanentlyException exception)
        {
            var redirectResult = new RedirectResult(exception.CannonicalUri);
            redirectResult.Permanent = true;

            return redirectResult;
        }
    }


  1. When I catch an exception derived from SaberpsicologiaException I want the appropiate handler to run:
    public class ExceptionHandlerFilter : ExceptionFilterAttribute
    {
        public override void OnException(ExceptionContext context)
        {
            base.OnException(context);

            HandleResponseCodeByExceptionType(context);
        }

        private void HandleResponseCodeByExceptionType(ExceptionContext context)
        {
            var exception = context.Exception;

            if (!CanHandle(exception))
            {
                return;
            }

            var mapping = new Dictionary<Type, Type>
            {
                { typeof(MovedPermanentlyException),  typeof(MovedPermanentlyExceptionHandler) }
            };

            var handlerType = mapping[exception.GetType()];
            var handler = Activator.CreateInstance(handlerType);

            handler.Result(exception); //<- compilation error 
            //handler is type "object" and not MovedPermanentlyExceptionHandler
        }
    }

I tried to resolve it with the Activator (Reflection), but I get to the problem of not really having and object of type ISaberpsicologiaExceptionHandler< [runtime exceptiontype] > so I can't have use the type properly.

In summary the problem is that I have an exception type and I want to get the ISaberpsicologiaExceptionHandler for that exception type, I guess I could use more reflection to just execute the 'Result' method, but I would like to do it a little bit more ellegant.





Aucun commentaire:

Enregistrer un commentaire