Me gustaría capturar todas las variantes de una clase de excepción genérica y me preguntaba si hay una manera de hacerlo sin múltiples bloques de captura. Por ejemplo, digamos que tengo una clase de excepción:
public class MyException<T> : Exception
{
public string MyProperty { get; }
public MyException(T prop) : base(prop.ToString())
{
MyProperty = prop?.ToString();
}
}
y dos clases derivadas:
public class MyDerivedStringException : MyException<string>
{
public MyDerivedStringException(string prop) : base(prop)
{
}
}
public class MyDerivedIntException : MyException<int>
{
public MyDerivedIntException(int prop) : base(prop)
{
}
}
¿Hay alguna manera de atrapar a ambos MyDerivedStringException
y MyDerivedIntException
en un bloque de captura?
He intentado esto:
try
{
...
}
catch(Exception e) when (e is MyDerivedStringException || e is MyDerivedIntException)
{
}
pero no está muy limpio y significa que no tengo acceso MyProperty
.
Estoy interesado en una solución general al problema, pero en mi caso la excepción genérica se define en una biblioteca de terceros que, como se señala a continuación, agrega algunas restricciones adicionales al problema.
Exception
yMyException<T>
estaría bien.La prueba si su
Type
deriva de un genérico es:Pero esto es cierto solo para los tipos derivados en sí, like
MyException<int>
oMyException<string>
.Si tiene más derivados como los
MyDerivedStringException
que tuvo que probar:Entonces, esto funciona para cualquier genérico existente, pero necesita conocer el nivel de herencia para esta prueba, o recorrer todos los tipos base.
Entonces podrías hacer esto:
fuente
Esta implementación encajona y desempaqueta si T: Value es Valuetype ... pero con respecto a la utilización puede controlar las implicaciones de rendimiento con la cantidad de veces que intenta encajonar / desempaquetar.
Lógica
fuente
Desafortunadamente, no puedes atrapar con el
catch(MyException ex)
clase, como se espera un tipo.Su mejor opción sería crear una clase base o interfaz, capturarla y obtener el tipo desde allí.
Ya existe una respuesta sobre lo que aquí sobre la manera de obtener el tipo y hacer esto.
fuente
esta implementación abstrae el delegado de manejo para el tipo de excepción fuera del contexto del T / C ... Esto puede ser un poco demasiado aventurero, pero lo bueno de esto es que puede inyectar diferentes manejadores dependiendo del alcance de la reutilización y el contexto de utilización.
lógica de registro
fuente