Korektní implementace tříd odvozených z Exception

Tomáš Holan       2. 7. 2012             5290 zobrazení

Pokud například v nějaké knihovně implementujeme veřejné třídy pro vlastní výjimky, měli by tyto třídy být implementované jako serializovatelné objekty. Obecně totiž nemusíme vědět, zda se nevyskytne případ, kdy exception objekt bude muset překročit hranici aplikační domény a pak by chybná implementace vadila.

Zajistit korektnost implementace tříd odvozených z Exception není přitom vůbec nic složitého, ale zase na druhou stranu to není úplně automatické a je tedy přece jenom potřeba něco málo dodržet.

Konkrétně jsou to tyto náležitosti:

  • Označit třídu atributem Serializable.
  • Doplnit protected nebo private (v případě sealed třídy) konstruktor s parametry SerializationInfoStreamingContext. Tento konstruktor provádí volání konstruktoru base(info, context) základní třídy a případnou deserializaci členských dat.
  • V případě vlastních členských dat doplnit implementaci metody GetObjectData pro serializaci těchto dat.

Všechny tyto body vychází z toho, že třída Exception pro serializaci implementuje interface ISerializable.

Implementace výjimky, která neobsahuje žádná vlastní členská data bude například následující:

[Serializable]
public class InvalidImportFileException : Exception, ISerializable
{
    #region constructors and destructors
    public InvalidImportFileException(string message) : base(message) { }

    public InvalidImportFileException(string message, Exception innerException) : base(message, innerException) { }

    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    protected InvalidImportFileException(SerializationInfo info, StreamingContext context) : base(info, context) { }
    #endregion
}

Explicitní uvedení, že naše třída implementuje interface ISerializable není nutná (již tak činí základní třída Exception), zde ho uvádím jen pro názornost.

Pokud by byla implementovaná třída sealed, byl by konstruktor s parametry SerializationInfoStreamingContext pouze private (tento konstruktor je při deserializaci objektu volán pomoci reflexe, takže to, že je private nevadí).

Implementace výjimky, která obsahuje vlastní členská data – v příkladu se jedná o vlastnost ProviderName -bude následující:

[Serializable]
public class ProviderException : Exception, ISerializable
{
    #region member varible and default property initialization
    public string ProviderName { get; private set; }
    #endregion

    #region constructors and destructors
    public ProviderException(string providerName, string message)
        : base(message)
    {
        if (providerName == null)
        {
            throw new ArgumentNullException("providerName");
        }

        this.ProviderName = providerName;
    }

    public ProviderException(string providerName, string message, Exception innerException)
        : base(message, innerException)
    {
        if (providerName == null)
        {
            throw new ArgumentNullException("providerName");
        }

        this.ProviderName = providerName;
    }

    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    protected ProviderException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
        if (info == null)
        {
            throw new ArgumentNullException("info");
        }

        this.ProviderName = (string)info.GetValue("ProviderName", typeof(string));
    }
    #endregion

    #region action methods
    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (info == null)
        {
            throw new ArgumentNullException("info");
        }

        info.AddValue("ProviderName", this.ProviderName);

        base.GetObjectData(info, context);
    }
    #endregion
}

Zde musíme navíc doplnit vlastní implementaci serializace a deserializace členských dat.

V konstruktoru ProviderException(SerializationInfo info, StreamingContext context) je logika pro jejich deserializaci a v metodě GetObjectData pro serializaci. Metoda GetObjectData musí dále provádět volání base implementace.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

RE: Korektní implementace tříd odvozených z Exception

VS ma k tomuto pekny code snippet "exception", ktory vygeneruje presny exception class podla 1. prikladu

Smad

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback