SpriteFont Serialization

Hello (happynuear !)

I am currently trying to make a class Thing serializable to be able to laod it from a save but i am facing a problem :
Thing have a SpriteFont field that i can’t get rid off now (i mean it is going to change a huge lot of things in my project and i would like to avoid that).

So, i made some researches and i found out that adding an empty and parameter free constructor inside a non-serializable class can resolve the issue of not being serializable (see there : https://support.microsoft.com/en-us/kb/330592).

So i wanted to to do that on the SpriteFont class but it is a sealed class and apparently that means i cannot edit this class. Unless there is a way ?

Another way that could work was to use :
public SpriteFont myFont {get;}
instead of
public SpriteFont myFont;

But in my Game1 file, the StorageManager that i am using is reached in the constructor of Game1, so, before my LoadContent() where is my LoadFont() method used to load every SpriteFont. So that means the StorageManager try to load the saved Thing class in which is a null SpriteFont because the SpriteFont should be loaded later in LoadFont().

Anyone have a solution ? The simplier the better :slight_smile:

Depending on how you are doing the serialization, you can use attributes to prevent some fields from being serialized. If you have [Serializable()] attribute on the class, add [NonSerialized()] to the SpriteFont field. See the documentation for SerializableAttribute for more information.

Thanks for the tip but it is not working.

This the execption (the part i am talking about is at the bottom, it is in french sorry for that) :
(just in case, after using your tip, error asks me to give a parameter without argument to the sealed SpriteFont class in order to solve my issue).

L’exception System.InvalidOperationException n’a pas été gérée
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du type ‘Pharmakon.Save’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
à System.Xml.Serialization.XmlSerializer…ctor(Type type, String defaultNamespace)
à Pharmakon.StorageManager.LoadGameConfiguration() dans D:\CURRENT PROJECT\DRONE AGENT nuArchi\428\DroneAgent\DroneAgent\StorageManager.cs:ligne 47
à Pharmakon.Game1…ctor() dans D:\CURRENT PROJECT\DRONE AGENT nuArchi\428\DroneAgent\DroneAgent\Game1.cs:ligne 72
à Pharmakon.Program.Main() dans D:\CURRENT PROJECT\DRONE AGENT nuArchi\428\DroneAgent\DroneAgent\Program.cs:ligne 16
à System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
à System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
à System.Threading.ThreadHelper.ThreadStart()
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du champ ‘Load_agent’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du type ‘Pharmakon.Agent’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du champ ‘drone’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du type ‘Pharmakon.Drone’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du champ ‘bar_hp’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du type ‘Pharmakon.Bar’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du champ ‘text’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Une erreur s’est produite lors de la réflexion du type ‘Pharmakon.Text’.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Impossible de sérialiser le membre ‘Pharmakon.Text.current_font’ de type ‘Microsoft.Xna.Framework.Graphics.SpriteFont’. Pour plus de détails, consultez l’exception interne.
Source=System.Xml
StackTrace:
à System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc, MemberInfo member, Type type)
à System.Xml.Serialization.StructModel.GetFieldModel(FieldInfo fieldInfo)
à System.Xml.Serialization.StructModel.GetFieldModel(MemberInfo memberInfo)
à System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
à System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
InnerException:
HResult=-2146233079
Message=Impossible de sérialiser Microsoft.Xna.Framework.Graphics.SpriteFont, car il n’a pas de constructeur sans paramètres.
InnerException:

As an additionnal information, the field on which i tried to use [NonSerialized()] is inside a class used by another class that is in the Serialized Thing class

Can you show some of the classes that you are trying to serialize?

Don’t know where to begin, maybe i can launch a twitch stream if you wanna see ?
go here https://www.twitch.tv/xxloudxx

I saw in the Twitch stream that you have an automatic property, not a field. Try changing

[NonSerialized] public SpriteFont current_font { get; set; }

to

[NonSerialized] SpriteFont currentFont;
public SpriteFont current_font { get { return currentFont; } set { currentFont = value; } }

I was thinking, Partial Class here; which might help with extending…

https://msdn.microsoft.com/en-us/library/wa80x488.aspx

Your solution is working to avoid serialization but after thinking in fact i can’t use it because i really need the text so i can’t use it.

So i (with the help of another developer) replaced the SpriteFont by a property getting a spritefont later by using a string serialized as a name of the spriteFont, like this :

public SpriteFont CurrentFont
        {
            get
            {
                if(loadedFont == null)
                {
                    loadedFont = Font.GetFontByName(current_font);
                }
                return Font.GetFontByName(current_font);
            }
        } 


static public SpriteFont GetFontByName(string name)
        {
            return Content.Load<SpriteFont>("Fonts/" +name);
        }
1 Like