serialized serialize deserialize clase attribute and c# exception serialization compact-framework

serialize - En C#, ¿cómo puedo serializar System.Exception?(.Net CF 2.0)



serialize attribute c# (7)

Comentario:

La serialización de excepciones es una tarea común cuando se busca de forma remota o interactúa con los sistemas a través de los límites del proceso. No escuche a nadie que diga lo contrario; probablemente nunca hayan escrito una biblioteca remota.

Solución:

He sondeado remotamente para hacer esto antes creando una clase de excepción base personalizada. El problema que encontré fue que System.Exception no se serializa fácilmente, así que tuve que heredar de él. La forma en que manejé esto fue creando mis propias excepciones que se serializaron (a través de ISerializable) y envolví cualquier excepción System.Exception en una excepción personalizada.

A lo largo de su código de servidor, debe usar excepciones personalizadas de todos modos, y todas pueden basarse en su tipo de base serializable. No es mucho trabajo, y creará rápidamente una biblioteca común de excepciones.

La capa que escribe en la cola (y leyó desde) debe hacer toda la serialización / hidratación de la excepción. Puede considerar algo como esto:

public class WireObject<T, E> { public T Payload{get;set;} public E Exception{get;set;} }

Las capas de servidor y cliente que hablan con su cola envolverán el objeto que está enviando en la Carga útil, o adjuntarán una excepción (si corresponde). Cuando los datos se consumen en la cola, la capa del cliente puede verificar una excepción y volver a lanzarla si está presente, de lo contrario, le entregará sus datos.

Esta es una versión muy simple de lo que he escrito antes, y lo que he visto que otros escriben. Buena suerte en tu proyecto.

Quiero escribir una excepción a una MS Message Queue. Cuando lo intento obtengo una excepción. Así que traté de simplificarlo usando el XmlSerializer, que aún genera una excepción, pero me dio un poco más de información:

{"Hubo un error que refleja el tipo ''System.Exception''."}

con InnerException:

{"No se puede serializar el miembro System.Exception.Data de tipo System.Collections.IDictionary, porque implementa IDictionary."}

Código de muestra:

Exception e = new Exception("Hello, world!"); MemoryStream stream = new MemoryStream(); XmlSerializer x = new XmlSerializer(e.GetType()); // Exception raised on this line x.Serialize(stream, e); stream.Close();

EDITAR: Intenté mantener esto lo más simple posible, pero es posible que me haya excedido. Quiero todo el bit, seguimiento de pila, mensaje, tipo de excepción personalizado y propiedades de excepción personalizadas. Puede que incluso quiera lanzar la excepción de nuevo.


¿Por qué? ¿Estás instanciando una excepción al recuperarla de la cola de mensajes? Si no, solo envíe el mensaje de excepción (como cadena) ...


Creo que básicamente tienes dos opciones:

  1. Haga su propia serialización manual (probablemente NO quiera hacer eso). La serialización XML seguramente no funcionará debido al mensaje exacto que recibe en la excepción interna.
  2. Cree su propia clase de excepción personalizada (serializable), inyecte los datos de la Excepción lanzada en la personalizada y serialícela.

No puede serializar un diccionario a xml. Haz lo que dijo el otro tipo y envía el mensaje, eso es lo importante de todos modos.


Seguí el método sugerido en este enlace (desplácese hacia abajo para la respuesta publicada por la persona llamada Kubilay) y funciona muy bien para mí. No es necesario crear ninguna clase de contenedor para el objeto de excepción.


Estaba viendo la respuesta de Jason Jackson, pero no tenía sentido para mí que tuviera problemas con esto a pesar de que System.Exception implementa ISerializable. Así que omití el XmlSerializer al envolver la excepción en una clase que usa un BinaryFormatter en su lugar. Cuando la serialización Xml de los objetos de MS Message Queue Server se activa, todo lo que verá es una clase con una matriz de bytes pública.

Esto es lo que se me ocurrió:

public class WrappedException { public byte[] Data; public WrappedException() { } public WrappedException(Exception e) { SetException(e); } public Exception GetException() { Exception result; BinaryFormatter bf = new BinaryFormatter(); MemoryStream stream = new MemoryStream(Data); result = (Exception)bf.Deserialize(stream); stream.Close(); return result; } public void SetException(Exception e) { MemoryStream stream = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(stream, e); Data = stream.ToArray(); stream.Close(); } }

La primera prueba funcionó perfectamente, pero todavía me preocupaban las excepciones personalizadas. Así que lancé mi propia excepción personalizada. Luego dejé caer un botón en un formulario en blanco. Aquí está el código:

[Serializable] public class MyException : Exception, ISerializable { public int ErrorCode = 10; public MyException(SerializationInfo info, StreamingContext context) : base(info, context) { ErrorCode = info.GetInt32("ErrorCode"); } public MyException(string message) : base(message) { } #region ISerializable Members void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("ErrorCode", ErrorCode); } #endregion } private void button1_Click(object sender, EventArgs e) { MyException ex = new MyException("Hello, world!"); ex.ErrorCode = 20; WrappedException reply = new WrappedException(ex); XmlSerializer x = new XmlSerializer(reply.GetType()); MemoryStream stream = new MemoryStream(); x.Serialize(stream, reply); stream.Position = 0; WrappedException reply2 = (WrappedException)x.Deserialize(stream); MyException ex2 = (MyException)reply2.GetException(); stream.Close(); Text = ex2.ErrorCode.ToString(); // form shows 20 // throw ex2; }

Aunque parecía que todos los demás tipos de excepciones que busqué están marcados con SerializableAttribute, tendré que tener cuidado con las excepciones personalizadas que no están marcadas con SerializableAttribute.

EDITAR: ir por delante de mí mismo. No me di cuenta de que BinaryFormatter no está implementado en CF.

EDITAR: los fragmentos de código anteriores estaban en un proyecto de escritorio. En la versión CF, la WrappedException se verá básicamente igual. Solo necesito implementar mi propio BinaryFormater, pero estoy muy abierto a sugerencias sobre eso.


Bueno, la serialización XML es limitada en sus usos. No puede, por ejemplo, serializar este escenario específico. Para la serialización exacta y la deserialización de Excepciones, debería usar un BinaryFormatter , que funcionaría siempre que sus propias excepciones estén marcadas como [Serializable] . Todas las excepciones .Net están marcadas con este SerializableAttribute , lo que significa que se pueden serializar con BinaryFormatter .

Sin embargo, hay un problema que debes tener en cuenta.
Si su excepción no es serializable, obviamente fallará. Pero también fallará cuando su excepción contenga un campo que no es serializable. Debe tener cuidado para asegurarse de que no sea posible en sus excepciones personalizadas.