Class Deep Copy. But...

EFileTahi-A

Contributor
Joined
Aug 8, 2004
Location
Portugal / Barreiro
But from a class that is inside another class.

Code:
[Serializable]
public class c_kaprical
{
    //my objects
[COLOR="Red"]    [Serializable] //<- this does not help.[/COLOR]
    public class c_solarSystem
    {
        //my objects

        public class c_kaprical.c_solarSystem Clone(c_kaprical.c_solarSystem newClone)
        {
            MemoryStream m = new MemoryStream();
            BinaryFormatter b = new BinaryFormatter();
            b.Serialize(m, newClone);
            m.Position = 0;
            return (c_kaprical.c_solarSystem)b.Deserialize(m);
        }
    }
}

This gives me an error saying that the class c_kaprical.c_solarSystem is not refered as Serializable. I've tried to tag c_solarSystem also with [Serializable]
This works well for c_kaprical class but for c_kaprical.c_solarSystem... :(

Any suggestions? I would love to keep this structure without removing the sub-classes from the main class. I just want to perform a deep copy of a given class despite of its method!

Thanks
 
Last edited:

snarfblam

Ultimate Contributor
Joined
Jun 10, 2003
Location
USA
Ideally, the framework would include a DeepCopy function. The needed functionality is already implemented in the BinaryFormatter class.

If this is a simple class, rolling your own deep copy function could be as simple as manually copying objects and assigning them to fields. And, as much as I am a champion of mutable types, using immutable types would make cloning trivial, as long as it doesn't cause the GC to thrash.

As to the question, I don't seem to be having the same problem with the run-time error. This is the code I used, which worked fine.

Code:
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args) {
            var s = new test.c_kaprical.c_solarSystem();
            var y = test.c_kaprical.c_solarSystem.Clone(s);
        }

    }
}

namespace test
{
    using System;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    [Serializable]
    public class c_kaprical
    {
        //my objects
        [Serializable] //<- this does not help.
        public class c_solarSystem
        {
            //my objects

            public static c_kaprical.c_solarSystem Clone(c_kaprical.c_solarSystem newClone) {
                MemoryStream m = new MemoryStream();
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(m, newClone);
                m.Position = 0;
                return (c_kaprical.c_solarSystem)b.Deserialize(m);
            }
        }
    }
}
Note that I changed "class" to "static" on the Clone method. I'm guessing that's just a transcribing error. Other than that, everything seems to be spiffy, but I'm working with a skeleton class here. If any of your fields are declared with non-serializable types, you will still get the error you're seeing.

Code:
    [Serializable]
    public class c_kaprical
    {
        //my objects
        [Serializable] //<- this does not help.
        public class c_solarSystem
        {
[COLOR="Red"]            SomethingElse anObject; // <-- ERROR: Field is of a non-serializable type!
[/COLOR]
            public static c_kaprical.c_solarSystem Clone(c_kaprical.c_solarSystem newClone) {
                // ...            
            }
        }

        // Not serializable
        class SomethingElse
        {
        }
    }
So my best guess: something in your object tree isn't serializable. The exception message should help you figure out what is causing the problem. The above code gave me this error:

Type 'test.c_kaprical+SomethingElse' in Assembly 'ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.​
 

EFileTahi-A

Contributor
Joined
Aug 8, 2004
Location
Portugal / Barreiro
Found the problem!

I was using two array lists containing a class: ArrayList<c_star> & ArrayList<c_celestialBody> inside the class c_solarSystem. They were NOT marked as Serializable. I simply added the tag [Serializable] to each one of them to make the whole thing work. All classes (c_star, c_solarSystem & c_celestialBody) are inside the main c_kaprical class (just a side note, kaprical is the name of the galaxy, yet the name of the game).

I could only achieve this thanks to your superb explanation.
Thanks! Once more...
 
Last edited:
Top Bottom