77 votes

Comment sérialiser un objet Exception en C #?

J'essaie de sérialiser un objet Exception en C #. Cependant, il semble que cela soit impossible car la classe Exception n'est pas marquée comme Serializable. Y a-t-il un moyen de contourner ce problème?

UPDATE : Si quelque chose ne va pas pendant l'exécution de l'application, je souhaite être informé de l'exception qui s'est produite. Mon premier réflexe est de le sérialiser ...

Merci!

54voto

David Crow Points 7704

Créez une classe d'exception personnalisée avec l'attribut [Serializable ()] . Voici un exemple tiré du MSDN :

 [Serializable()]
public class InvalidDepartmentException : System.Exception
{
    public InvalidDepartmentException() { }
    public InvalidDepartmentException(string message) : base(message) { }
    public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { }

    // Constructor needed for serialization 
    // when exception propagates from a remoting server to the client.
    protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,
        System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
 

44voto

davogones Points 5405

Ce que j'ai déjà fait est de créer une classe d'erreur personnalisée. Cela encapsule toutes les informations pertinentes sur une exception et permet la sérialisation XML.

 [Serializable]
public class Error
{
    public DateTime TimeStamp { get; set; }
    public string Message { get; set; }
    public string StackTrace { get; set; }

    public Error()
    {
        this.TimeStamp = DateTime.Now;
    }

    public Error(string Message) : this()
    {
        this.Message = Message;
    }

    public Error(System.Exception ex) : this(ex.Message)
    {
        this.StackTrace = ex.StackTrace;
    }

    public override string ToString()
    {
        return this.Message + this.StackTrace;
    }
}
 

44voto

Rex M Points 80372

La classe Exception est marquée en tant que Serializable et implémente ISerializable. Voir MSDN: http://msdn.microsoft.com/en-us/library/system.exception.aspx

Si vous essayez de sérialiser au format XML en utilisant les XmlSerializer , vous rencontrerez une erreur sur tous les membres qui implémentent IDictionary . C'est une limitation de XmlSerializer, mais la classe est certainement sérialisable.

17voto

Antony Booth Points 141

mson a écrit: "Je ne sais pas pourquoi vous voudriez sérialiser l'exception ..."

Je sérialise les exceptions pour faire passer l'exception, via un service Web, à l'objet appelant qui peut le désérialiser, puis le retransmettre, le consigner ou le gérer.

J'ai fait ça. J'ai simplement créé une classe wrapper Serializable qui remplace l'IDictionary par une alternative sérialisable (tableau KeyValuePair)

 /// <summary>
/// A wrapper class for serializing exceptions.
/// </summary>
[Serializable] [DesignerCategory( "code" )] [XmlType( AnonymousType = true, Namespace = "http://something" )] [XmlRootAttribute( Namespace = "http://something", IsNullable = false )] public class SerializableException
{
    #region Members
    private KeyValuePair<object, object>[] _Data; //This is the reason this class exists. Turning an IDictionary into a serializable object
    private string _HelpLink = string.Empty;
    private SerializableException _InnerException;
    private string _Message = string.Empty;
    private string _Source = string.Empty;
    private string _StackTrace = string.Empty;
    #endregion

    #region Constructors
    public SerializableException()
    {
    }

    public SerializableException( Exception exception ) : this()
    {
        setValues( exception );
    }
    #endregion

    #region Properties
    public string HelpLink { get { return _HelpLink; } set { _HelpLink = value; } }
    public string Message { get { return _Message; } set { _Message = value; } }
    public string Source { get { return _Source; } set { _Source = value; } }
    public string StackTrace { get { return _StackTrace; } set { _StackTrace = value; } }
    public SerializableException InnerException { get { return _InnerException; } set { _InnerException = value; } } // Allow null to be returned, so serialization doesn't cascade until an out of memory exception occurs
    public KeyValuePair<object, object>[] Data { get { return _Data ?? new KeyValuePair<object, object>[0]; } set { _Data = value; } }
    #endregion

    #region Private Methods
    private void setValues( Exception exception )
    {
        if ( null != exception )
        {
            _HelpLink = exception.HelpLink ?? string.Empty;
            _Message = exception.Message ?? string.Empty;
            _Source = exception.Source ?? string.Empty;
            _StackTrace = exception.StackTrace ?? string.Empty;
            setData( exception.Data );
            _InnerException = new SerializableException( exception.InnerException );
        }
    }

    private void setData( ICollection collection )
    {
        _Data = new KeyValuePair<object, object>[0];

        if ( null != collection )
            collection.CopyTo( _Data, 0 );
    }
    #endregion
}
 

10voto

mmr Points 7094

Si vous essayez de sérialiser l'exception d'un journal, il vaudrait mieux ne faire qu'un .ToString(), puis sérialiser que pour votre journal.

Mais voici un article sur la façon de le faire, et pourquoi. Fondamentalement, vous avez besoin pour mettre en œuvre ISerializable sur votre exception. Si c'est un système d'exception, je crois qu'ils ont que l'interface de mise en œuvre. Si c'est quelqu'un d'autre exception, vous pourriez être en mesure à la sous-classe pour implémenter l'interface ISerializable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X