Link to home
Start Free TrialLog in
Avatar of gamesmeister
gamesmeisterFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Serialization and Event Publishers

Hi

I have an application consisting of Form A and Class B. Class B stores a set of values that I want to save to file, and is therefore Serializable. However, I also added an event to it so that when one of the values changed, a subscriber (in this case Form A) was notified, and could refresh itself.

What actually happened was that when I attempted to write Class B to a filestream, it failed with a 'NonSerializable object' error - the object in question was the form.

Is this because I've added the form to Class B as a subscriber, and therefore .NET assumes it must also serialize the form? Assuming it is, what is the 'best practice' for dealing with this situation, bearing in mind that I can't mark an event as NonSerializable? Encapsulate Class B within another class that publishes the event? (I was hoping to avoid this, as it takes the responsibility of its own objects away from Class B, and means every change to variables within Class B will have to go through this wrapper).

Many thanks
Gerry
Avatar of AlexFM
AlexFM

Please show your code.
Avatar of gamesmeister

ASKER

Code as follows (names changed to protect the innocent). When I try to serialize an instance of MyClass, I get the following error
********************************************************************
An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll

Additional information: The type MyForm in Assembly MyExe, Version=1.0.1886.24124, Culture=neutral, PublicKeyToken=null is not marked as serializable.
**********************************************************************

public class MyForm
{
      public MyForm()
      {
            MyClass mc = new MyClass();
            mc.ArrayListChanged +=new EventHandler(mc_ArrayListChanged);
      }
      

      private void mc_ArrayListChanged(object sender, EventArgs e)
      {
            //update list view on Form
      }
}


[Serializable]
public class MyProject
{
      private ArrayList myArray;
      protected event EventHandler arrayListChanged;

      public MyProject()
      {
            myArray = new ArrayList();
      }

      public event EventHandler ArrayListChanged
      {
            add      {arrayListChanged += value;}
            remove {arrayListChanged -= value;}
      }

      public void AddString(string myString)
      {
            myArray.Add(myString);
            if (arrayListChanged != null)
            {
                  OnArrayListChanged(new EventArgs());
            }
      }

      protected void OnArrayListChanged(System.EventArgs e)
      {
            arrayListChanged (this, e);
      }
}
Sorry, the class should be called MyClass, not MyProject
Where is serialization code? It looks like you are trying to serialize MyForm and not MyClass.
The Serialization code is in a class library, called from MyForm. It receives an object and a path, and saves it as per the following. The object I'm passing as 'data' is the instance of MyClass (mc). One other thing - this all worked fine until I added the event handler to MyClass

public class BinaryPersistence : IPersistence
{
      private object storedData;
      private Stream stream;
      
      public BinaryPersistence()
      {
      }

      public void StoreFile(object data, string path)
      {
            if (data.Equals(null))
            {
                  throw (new ArgumentNullException("data", "No data passed to store"));
            }
            else
            {
                  if (path.Equals(null))
                  {
                        throw (new ArgumentNullException("path", "Filename cannot be null"));
                  }
            }
      
            stream = new FileStream(path,FileMode.Create,FileAccess.Write);
            StoreStream(data);
      }
      
      private void StoreStream(object data)
      {
            IFormatter f = new BinaryFormatter();
            f.Serialize(stream, data);
            stream.Close();
      }

}
From the lack of response, can I assume that it's normally perfectly ok to add Event Handlers to a serializable class, and that there's something else wrong here?
Currently I have no answer, I will try to make small test later.
ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
That's an excellent workaround, thanks Alex