C # Cloning - working with non-serializable data types

I hit a little stumbling block in my quest to implement object cloning in my game engine. My goal is to have a cloning system that I don’t need to maintain in a class by class, unless the class needs special treatment.

My game engine setup revolves around the Object2D base class, which contains some image data in the form of Texture2D. Well, the long story is that it has a DisplayObject that contains Sprite, which contains Texture2D. Naturally, other classes, for example. "Player", "Enemy", "Projectile", etc. Produced from the base class Object2D.

Unfortunately, I found that the XNA Texture2D class is not serializable. This makes sense, since we would not want to duplicate the texture data in memory all willingly.

This creates a dilemma for me. I used cloning methods to clone objects, but since it is not serializable, I can no longer do this. I tried just to mark Texture2D [NonSerializable], but this causes problems when trying to draw, since the texture of the clone is zero. I was unable to find any hidden trick that allows me to assign it after cloning (sort of like the onClone () method).

So I decided that I would do it. For objects that cannot be deeply cloned as a whole, I implement the "SpecialClone" interface, which allows me to specify the clone () method.

However, since a class that cannot be completely cloned as a whole is a base class, I will go back to where I started: writing the clone method for a class by class.

public static T clone<T>(T obj) { if (obj == null) return default(T); if (!typeof(T).IsSerializable) { if (obj is SpecialClone) { object obj2 = ((SpecialClone)obj).clone(); return (T)obj2; } else { throw new ArgumentException("Object type is not serializable.", "obj type: " + Type.GetTypeHandle(obj)); } } else { return deepClone(obj); } } public static T deepClone<T>(T obj) { if (obj == null) return default(T); if (typeof(T).IsSerializable) { try { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, obj); ms.Seek(0, SeekOrigin.Begin); T obj2 = (T)bf.Deserialize(ms); ms.Dispose(); return obj2; } catch (Exception e) { Console.WriteLine(e); return default(T); } } else { Console.WriteLine(typeof(T) + " is not marked as serializable!"); return default(T); } } 

I'm still not the best with C #, so I'm not sure if I am missing any trick I can use, or, if that is the case, I will have to deal with this problem. The main purpose of this cloning is for Object2D types, so it would be a real pain to write cloning methods for every new subclass I make.

Is there any way to avoid this?

+4
source share
2 answers

You do not want to clone Texture2d.

You should consider Textures (and models, wave files, etc.) as a "common resource", it can be many megabytes in size. Cloning that would leave you in a world without memory would hurt very quickly (in addition to the time it takes for cloning)

your ideal solution:, you want to clone the link.

If each of the Object2D instances is not intended for serialization, you can simply reference the same Texture2D to different Object2D objects. If you want to serialize, then pass the Texture2D link, as already mentioned, plus copy the line textureFilePath, which is serialization.

Also note that this is what XNA ContentManager does for you automatically: if you request "myPic.xnb" 10 times, it will automatically download it once and return this link to you 10 times.

+1
source

ICloneable (.Net network interface) is better than SpecialClone. You can also implement the ISerializable interface with the ctor protected constructor (SerializationInfo information, StreamingContext context).

This will allow you to customize serialization (SerializationInfo is a bag that can contain everything you need to deserialize the object later and is passed to you in a protected constructor).

So, all you need to know about serialization. If you can do this or not, it depends on whether there is something in the non-serializable class (i.e. Key, file name, buffer) that you can use when deserializing to recreate this object.

0
source

Source: https://habr.com/ru/post/1380920/


All Articles