views:

316

answers:

1

I have a class that handles serialization in C#, called Serializer. It's implementation is below:

public class Serializer
{
    public void SerializeRulesManager(string filename, RulesManager rulesManager)
    {
        Stream stream = File.Open(filename, FileMode.Create);        
        try
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            binaryFormatter.Serialize(stream, rulesManager);             
        }
        finally
        {
            stream.Close();
        }                
    }

    public RulesManager DeserializeRulesManager(string filename)
    {
        RulesManager rulesManager = null;
        Stream stream = File.Open(filename, FileMode.Open);
        try
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            rulesManager = (RulesManager)binaryFormatter.Deserialize(stream);                
        }
        finally
        {
            stream.Close();                
        }                       
        return rulesManager;
    }
}

Pretty straightforward stuff, and it works just fine with all of my unit tests. The RulesManager is correctly serialized and deserialized so I know the graph is good.

The trouble comes with the following code:

public void Save(string filename)
{
    Cursor.Current = Cursors.WaitCursor;
    try
    {
        _serializer.SerializeRulesManager(filename, _rulesManager);
    }
    catch (System.Exception ex)
    {
        MessageBox.Show(ex.Message);
    }            
    finally
    {
        Cursor.Current = Cursors.Default;
    }
}

That function is part of the Manager class. The Manager class is instantiated on the MainForm. The MainForm uses a SaveFileDialog to prompt the user for the filename and location they want to save to and then makes the following call:

saveFileDialog.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath);
if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
{
    _manager.Save(saveFileDialog.FileName);
}

Thus calling the function above. When it does so, I get the following exception in Serialize.SerializeRulesManager at the binaryFormatter.Serialize(stream, rulesManager) line:

Type 'TestHarness.MainForm' in Assembly 'TestHarness, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

Why would MainForm need to be marked as Serializable? Just for kicks, I put the Serializable attribute on MainForm and it just moved the exception up one level to say that Windows.Form was not marked as Serializable. What gives?

+4  A: 

RulesManager probably has a reference to MainForm. If so, mark it as not serialized with the NonSerializedAttrbibute

Greg Dean
Well that's what I get for posting at the end of a work-day instead of sleeping on it. I completely overlooked the event exposed by RulesManager that MainForm was hooked to. The even wasn't marked as [field:NonSerializable] and I wasn't unhooking the event in the MainForm and so it was trying to serialize the MainForm as well.Marking the event as [field:NonSerializable] fixed the problem.
Scott