2009-07-08 12 views
5

Cuando se trata de excepciones personalizadas, por lo general heredan de Excepción y luego añadir algunos campos/propiedades a mi clase de excepción para almacenar alguna información adicional:¿Cómo debo almacenar datos dentro de excepciones personalizadas?

public class MyException : Exception 
{ 
    public int ErrorCode{get;set;} 

    public MyException() 
    {} 
} 

En el ejemplo anterior, el valor ErrorCode se almacena en la excepción , lo que significa que tengo que agregarlo y retirarlo si desde el objeto SerializationInfo en el constructor protegido y el método Oreemplazado.

La clase Exception tiene una propiedad Data, que según MSDN:

Obtiene una colección de pares clave/valor que proporcionan información adicional definida por el usuario sobre la excepción.

Si puedo almacenar el código de error dentro de la Data, se pondrá en serie para mí por la clase de excepción (de acuerdo con reflector), lo que significa que mi clase de excepción ahora se ve como:

public class MyException : Exception 
{ 
    public int ErrorCode 
    { 
     get {return (int) Data["ErrorCode"];} 
     set {Data["ErrorCode"] = value;} 
    } 

    public MyException() 
    {} 
} 

Estos medios que si bien hay un poco más de trabajo para hacer frente al get/set del código de error (como tratar con los errores de transmisión y las situaciones en las que el código de error podría no estar en el diccionario), no tengo que preocuparme por la serialización/deserializándolo

¿Es esto solo dos formas diferentes de lograr lo mismo, o una forma tiene alguna ventaja clara sobre la otra (aparte de las que ya he mencionado)?

Respuesta

1

Evitaría el uso de datos, ya que no está bajo su control, p. algún código en alguna parte puede decidir sobreescribir el valor "ErrorCode". En su lugar, use la propiedad e implemente la serialización. Uso el siguiente código para probar todas mis excepciones personalizadas para asegurarme de haberlas implementado correctamente.

public static void TestCustomException<T>() where T : Exception 
{ 
    var t = typeof(T); 

    //Custom exceptions should have the following 3 constructors 
    var e1 = (T)Activator.CreateInstance(t, null); 

    const string message = "message"; 
    var e2 = (T)Activator.CreateInstance(t, message); 
    Assert.AreEqual(message, e2.Message); 

    var innerEx = new Exception("inner Exception"); 
    var e3 = (T)Activator.CreateInstance(t, message, innerEx); 
    Assert.AreEqual(message, e3.Message); 
    Assert.AreEqual(innerEx, e3.InnerException); 

    //They should also be serializable 
    var stream = new MemoryStream(); 
    var formatter = new BinaryFormatter(); 
    formatter.Serialize(stream, e3); 
    stream.Flush(); 
    stream.Position = 0; 
    var e4 = (T)formatter.Deserialize(stream); 
    Assert.AreEqual(message, e4.Message); 
    Assert.AreEqual(innerEx.ToString(), e4.InnerException.ToString()); 
} 
0

Debe ir con la primera solución. No puedo ver mucho valor en la propiedad de datos, a menos que planee subir instancias de excepción de fila con infos adjuntos.

Si tiene su propio tipo de excepción, entonces use propiedades en su lugar: es más limpio y seguro.

1

Microsoft's own guidelines:

sí hacen excepciones serializable. Una excepción debe ser serializable para funcionar correctamente en el dominio de la aplicación y los límites remotos.

Lo almacenaba en la propiedad de datos, que lamentablemente permitiría que el código externo modifique el valor sin consentimiento, o utilice la solución 1 (en su ejemplo) pero que sea serializable. Al final, probablemente buscaría la solución 1, así puedo estar seguro de que el valor nunca cambia.

5

Si se molesta en crear su propia excepción, no necesita la propiedad Data. Los datos son útiles cuando desea almacenar un poco de información adicional en una clase de excepción existente, pero no desea crear su propia clase de excepción personalizada.

Cuestiones relacionadas