Serializing Exceptions

Posts   
 
    
Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 29-Dec-2004 09:30:57   

So, I want to create an exception that is serializable and sealed.

I have a WizardBaseException that inherits ApplicationException:

 [Serializable()]
public class WizardBaseException:ApplicationException
{
// code omitted
}

I provide a constructor for deserialization where I initialize all my member variables:

        protected WizardBaseException(SerializationInfo info, StreamingContext context):
            base(info, context)
        {
            Initialize();
            assemblyName = info.GetString(assemblyNameKey);
            utcDateTime = info.GetDateTime(utcDateTimeKey);
            appDomainName = info.GetString(appDomainNameKey);
            currentProcessId = info.GetString(currentProcessIdKey);
            currentThreadId = info.GetString(currentThreadIdKey);
            currentThreadUser = info.GetString(currentThreadUserKey);
            machineName = info.GetString(machineNameKey);
        }   

I also override GetObjectData to serialize all the members into the streaming context:

        public override void GetObjectData(SerializationInfo info
            , StreamingContext context)
        {
            info.AddValue(appDomainNameKey, appDomainName, StringType);
            info.AddValue(assemblyNameKey, assemblyName, StringType);
            info.AddValue(currentProcessIdKey,currentProcessId,IntegerType);
            info.AddValue(currentThreadIdKey, currentThreadId, IntegerType);
            info.AddValue(currentThreadUserKey, CurrentThreadUser, StringType);
            info.AddValue(machineNameKey, machineName, StringType);
            info.AddValue(utcDateTimeKey, utcDateTime, DateTimeType);

            base.GetObjectData (info, context);
        }

This works great. Here is the kicker, when I create a concrete custom exception that is not inheritable:

    [Serializable]
    public sealed class InvalidWizardId:WizardBaseException
    {//.... code omitted}

and I include the protected constructor so that the runtime can deserialize my exception like so:

        protected InvalidWizardId(SerializationInfo info, StreamingContext context):
            base(info,context)
        {
            
        }

I get the following compiler warning:

 'member' : new protected member declared in sealed class

A sealed class cannot introduce a protected member because no other class will be able to inherit from the sealed class and use the protected member.

The following sample generates CS0628:

// CS0628.cs
// compile with: /W:4


This makes sense sort of, but I thought the framework used the constructor to deserialize the exception. Is this warning going to cause an exception somewhere down the line that I am not aware of or can this simply be ignored.

In the end, what really needs to happen is that during deserialization the members of InvalidWizardId need to be populated using the serialization info, where else could this be done other than the protected constructor?

I suppose I could just make InvalidWizardId not sealed and let other developers worry about it, but a quick sanity check would be nice.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39752
Joined: 17-Aug-2003
# Posted on: 29-Dec-2004 10:52:43   

You can make that constructor private, that's not important. Private, public, it's syntactical sugar, the CLR doesn't know about private or public. The serializer simply calls the constructor through reflection anyway.

The datatable's getobjectdata method for example is implemented private, but works ok simple_smile

You can also not provide 'sealed'. Sealed is a keyword that often does more harm than good, IMHO.

Frans Bouma | Lead developer LLBLGen Pro
Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 30-Dec-2004 22:36:26   

Or.... I could use the /nowarn 628 compiler option to suppress the level 4 warning.

Frans, you have mentioned many times that sealed objects cause headaches at times. Does this stem from the fact that often times you find a class with an interface and does everything you need except for 1 thing but you cannot extend it because its sealed, or are there other reasons besides the afore mention one?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39752
Joined: 17-Aug-2003
# Posted on: 31-Dec-2004 15:01:21   

Devildog74 wrote:

Frans, you have mentioned many times that sealed objects cause headaches at times. Does this stem from the fact that often times you find a class with an interface and does everything you need except for 1 thing but you cannot extend it because its sealed, or are there other reasons besides the afore mention one?

No that's basicly it.

I mean, why shouldn't I have the ability to inherit from a class and add my own utility methods to it which make the class more richer?

The same goes for making methods not virtual. It takes a few steps away from the code, but it's often helpful to make some methods virtual so developers can easily extend code. I do have to add that I made some horrible mistakes with this in the runtime lib flushed like: making methods virtual but overriding them would require a complete rewrite of the base method, so the extensibility I had in mind was totally not there smile .

Frans Bouma | Lead developer LLBLGen Pro