practices - .NET: ¿Qué excepción lanzar cuando falta una configuración de configuración requerida?
throw exception c# (11)
¿Qué pasa con System.Configuration.SettingsPropertyNotFoundException?
Aquí hay un escenario estándar:
if(string.IsNullOrEmpty(Configuration.AppSettings["foobar"]))
throw new SomeStandardException("Application not configured correctly, bozo.");
El problema es que no estoy del todo seguro de qué excepción debería ser SomeStandardException
.
Analicé el Framework 3.5 y encontré dos posibles candidatos: ConfigurationException
y ConfigurationErrorsException
.
System.Configuration.ConfigurationException
La excepción que se produce cuando se ha producido un error en el sistema de configuración.
Observaciones
La excepciónConfigurationException
se lanza si la aplicación intenta leer o escribir datos en el archivo de configuración pero no tiene éxito. Algunas razones posibles para esto pueden incluir XML mal formado en el archivo de configuración, problemas de permisos de archivos y propiedades de configuración con valores que no son válidos.Nota:
El objeto
ConfigurationException
se mantiene por compatibilidad con versiones anteriores. El objetoConfigurationErrorsException
reemplaza por el sistema de configuración.
Esta excepción en realidad suena perfecta para lo que necesito, pero se ha marcado como obsoleta, así que, ixnay en atthay.
Esto nos lleva a la completamente confusa ConfigurationErrorsException
:
System.Configuration.ConfigurationErrorsException
El valor actual no es uno de los valores de EnableSessionState.
Como puede ver, su documentación es completamente inútil. (Es así en la ayuda local y en línea.) Un examen de la clase en sí muestra que es una exageración drástica para lo que quiero.
En pocas palabras, necesito una excepción estándar que se debe lanzar cuando falta una configuración de la aplicación o contiene un valor no válido. Uno pensaría que el Framework tenía una excepción para las aplicaciones. (Aparentemente sí, pero se marcó como obsoleto y fue reemplazado por algo mucho más amplio).
¿Qué soluciones, si hay alguna, usan ustedes para esto, y voy a tener que aguantar y lanzar mi propia excepción para esto?
Editar adenda
Algunos me han preguntado si puedo proporcionar un valor predeterminado o no y continúo. En ciertos casos, sí, y en esos casos, la excepción no se lanzará. Sin embargo, para ciertas configuraciones, esto no se aplicará. Por ejemplo: nombres y credenciales del servidor de bases de datos, servidores de autenticación y rutas a aplicaciones de terceros instaladas.
También vale la pena señalar que la aplicación en la que estoy trabajando principalmente es una aplicación de consola que se ejecuta en modo batch, y quiero que arroje una excepción que sea captada por el método principal y registrada apropiadamente si la cosa no está configurada adecuadamente. (Es el código heredado que heredé, y actualmente solo asumo que todo es color de rosa).
Como dijo Daniel Richardson, ConfigurationErrorsException es el que se debe usar. En general, solo se recomienda crear sus propios tipos de excepción personalizados si tiene un escenario para manejarlos. En el caso de los errores de configuración, que generalmente son fatales, rara vez es así, por lo que suele ser más apropiado reutilizar el tipo ConfigurationErrorsException existente.
Antes de .NET 2.0, la recomendación era usar System.Configuration.ConfigurationException . ConfigurationException quedó obsoleto en .NET 2.0, por razones que nunca tuve claras, y la recomendación cambió para usar ConfigurationErrorsException.
Utilizo un método auxiliar para lanzar la excepción, de modo que es fácil cambiar la excepción que se lanza en un lugar al migrar de .NET 1.xa 2.0, o si Microsoft decide cambiar la recomendación nuevamente:
if(string.IsNullOrEmpty(Configuration.AppSettings("foobar")))
{
throw CreateMissingSettingException("foobar");
}
...
private static Exception CreateMissingSettingException(string name)
{
return new ConfigurationErrorsException(
String.Format
(
CultureInfo.CurrentCulture,
Properties.Resources.MissingConfigSetting,
name
)
);
}
ConfigurationErrorsException es la excepción correcta para incluir en la situación que describes. Una versión anterior de la documentación de MSDN para ConfigurationErrorsException tiene más sentido.
El resumen y observaciones anteriores de MSDN son:
- La excepción que se produce cuando se produce un error del sistema de configuración.
- La excepción ConfigurationErrorsException se produce cuando se produce un error mientras se lee o escribe la información de configuración.
La clase ConfigurationElement (que es la clase base de muchas clases relacionadas con la configuración, como ConfigurationSection) tiene un método llamado OnRequiredPropertyNotFound (también hay otros métodos auxiliares). Tal vez puedas llamar a esos.
OnRequiredPropertyNotFound se implementa de esta manera:
protected virtual object OnRequiredPropertyNotFound(string name) {
throw new ConfigurationErrorsException(SR.GetString("Config_base_required_attribute_missing", new object[] { name }), this.PropertyFileName(name), this.PropertyLineNumber(name)); }
Mi regla general sería:
Si el caso de la configuración faltante no es muy común y creo que nunca querría manejar este caso de forma diferente a otras excepciones, solo uso la clase básica "Excepción" con un mensaje apropiado:
lanzar nueva excepción ("mi mensaje aquí")
Si quiero, o creo que hay una gran probabilidad de que quisiera manejar este caso de una manera diferente a la mayoría de las demás excepciones, publicaría mi propio tipo como ya lo han sugerido las personas aquí.
No está limitado en su excepción, lanzando a las excepciones existentes en el Marco. Si decide utilizar excepciones existentes, no tiene que seguir la documentación al pie de la letra. La documentación describirá cómo el marco utiliza una excepción dada, pero no implica ninguna limitación sobre cómo elige usar / reutilizar una excepción existente.
Es su aplicación, siempre que la documente y indique claramente la excepción que se arrojará en el caso específico de un valor de configuración faltante, puede usar cualquier excepción que desee. Si desea una indicación muy específica de un valor perdido , puede considerar escribir su propia excepción ConfigurationSettingMissing:
[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}
EDITAR: Escribir su propia excepción en este caso conlleva el beneficio adicional de garantizar que nunca haya confusión sobre el origen de la excepción: el marco o su aplicación. El marco nunca arrojará sus excepciones personalizadas.
ACTUALIZACIÓN: estoy de acuerdo con los comentarios, por lo que he cambiado la subclase a ConfigurationErrorsException de Exception. Creo que generalmente es una buena idea subclasificar las excepciones personalizadas de las excepciones existentes de Framework siempre que sea posible, evitando la clase Exception a menos que necesite una excepción específica de la aplicación.
Personalmente, usaría InvalidOperationException , ya que es un problema con el estado del objeto, no con el sistema de configuración. Después de todo, ¿no debería permitir que estas configuraciones sean configuradas por código y no por configuración también? La parte importante aquí no es que no haya línea en app.config, sino que una información requerida no estaba presente.
Para mí, ConfigurationException (y su reemplazo, ConfigurationErrorsException, a pesar de los engañosos documentos de MSDN) son para errores en el guardado, lectura, etc. de la Configuración.
Podría tratar de heredar la excepción XML o simplemente usarla.
Tiendo a estar en desacuerdo con la premisa de su pregunta:
En pocas palabras, necesito una excepción estándar que se debe lanzar cuando falta una configuración de la aplicación o contiene un valor no válido. Uno pensaría que el Framework tenía una excepción para las aplicaciones. (Aparentemente sí, pero se marcó como obsoleto y fue reemplazado por algo mucho más amplio).
De acuerdo con la documentación de MSDN sobre System.Exception ( Exception Class) , no debería arrojar excepciones para los errores de entrada del usuario, por razones de rendimiento (que otros apuntaron en y en otros lugares). Esto parece tener sentido ya que Bien, ¿por qué su función no puede ser falsa si la entrada del usuario se ingresó incorrectamente y luego la aplicación sale graciosamente? Esto parece ser más un problema de diseño que un problema con el cual Exception lanzar.
Como han señalado otros, si realmente tiene que lanzar una excepción, por cualquier razón, no hay ninguna razón por la cual no pueda definir su tipo de Excepción heredando desde System.Exception.
Un método alternativo que podría usar para sus archivos de configuración sería usar secciones de configuración personalizadas en lugar de AppSettings
. De esta forma, puede especificar que una propiedad se IsRequired
y el sistema de configuración se encargará de esta comprobación por usted. Si falta la propiedad arrojará una excepción ConfigurationErrorsException
así que supongo que admite la respuesta de que debe usar esa excepción en su caso.
Yo lo chuparé y sacaré el mío ... pero antes de hacerlo, ¿es posible que el sistema asuma un valor predeterminado para esta configuración? Por lo general, intento hacer eso para cada entorno que pueda perderse en la administración de operaciones de Ops ... (o tal vez debería decir, para tantos ajustes como sea posible; para algunos, claramente no es apropiado que el sistema tome una decisión predeterminada). ..)
en general, una excepción personalizada no es un gran esfuerzo ... aquí hay un ejemplo ...
[Serializable]
public class MyCustomApplicationException : ApplicationException
{
#region privates
#endregion privates
#region properties
#endregion properties
public MyCustomApplicationException (string sMessage,
Exception innerException)
: base(sMessage, innerException) { }
public MyCustomApplicationException (string sMessage)
: base(sMessage) { }
public MyCustomApplicationException () { }
#region Serializeable Code
public MyCustomApplicationException (
SerializationInfo info, StreamingContext context)
: base(info, context) { }
#endregion Serializeable Code
}