0

I'm getting weird error when serializing this XML:

<?xml version="1.0" encoding="utf-8" ?>
<SplashScreen>
  <Image>
    <Path>Content/splash</Path>
  </Image>
</SplashScreen>

Error:

"A first chance exception of type 'System.InvalidOperationException' occurred in System.Xml.dll Additional information: Reflecting on the type of error occurred EasyRPG.SplashScreen. If there is a handler for this exception, the program may be safely continued."

XMLManager class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace EasyRPG.Managers {
public class XmlManager<T> {

    public Type Type;

    public T Load (String path) {
        T instance;
        using (TextReader reader = new StreamReader(path)){
            XmlSerializer xml = new XmlSerializer(Type);
            instance = (T)xml.Deserialize(reader);
        }
        return instance;
    }

    public void Save (string path, object obj) {
        using (TextWriter writer = new StreamWriter(path)) {
            XmlSerializer xml = new XmlSerializer(Type);
            xml.Serialize(writer, obj);
        }
    }
}
}

I am lost, I tried everything I know(that's not much though) and still nothing.

Image class if needed:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using EasyRPG;

namespace TEAM_TheCity.Source {
public class Image {

    public float Alpha;
    public string Path;
    public string Text, FontName;
    public Vector2 Position;

    public Vector2 Scale;
    public Rectangle SourceRect;

    public SpriteFont font;
    public GraphicsDevice GraphcsDevice;
    public Texture2D Texture;
    Vector2 origin;

    ContentManager content;
    RenderTarget2D renderTarget;
    public SpriteBatch SpriteBatch;

    public Image () {
        Path = Text = String.Empty;
        FontName = "Orbitron";
        Position = Vector2.Zero;
        Scale = Vector2.One;
        Alpha = 1.0F;
        SourceRect = Rectangle.Empty;
    }

    public void LoadContent(){
        content = new ContentManager(ScreenManager.Manager.Content.ServiceProvider, "Content");

        if(Path != String.Empty) Texture = content.Load<Texture2D>(Path);

        font = content.Load<SpriteFont>(FontName);

        Vector2 dimensions = Vector2.Zero;

        if(Texture != null)
            dimensions.X += Texture.Width;
        dimensions.X += font.MeasureString(Text).X;

        if(Texture != null)
            dimensions.Y = Math.Max(Texture.Height, font.MeasureString(Text).Y);
        else
            dimensions.Y = font.MeasureString(Text).Y;

        if(SourceRect == Rectangle.Empty)
            SourceRect = new Rectangle(0,0, (int)dimensions.X, (int)dimensions.Y);

        renderTarget = new RenderTarget2D(ScreenManager.Manager.GraphicsDevice,(int) dimensions.X, (int)dimensions.Y);
        ScreenManager.Manager.GraphicsDevice.SetRenderTarget(renderTarget);
        ScreenManager.Manager.GraphicsDevice.Clear(Color.Transparent);
        ScreenManager.Manager.SpriteBatch.Begin();
        if (Texture != null)
            ScreenManager.Manager.SpriteBatch.Draw(Texture, Vector2.Zero, Color.White);
        ScreenManager.Manager.SpriteBatch.DrawString(font, Text, Vector2.Zero, Color.White);
        ScreenManager.Manager.SpriteBatch.End();

        Texture = renderTarget;

        ScreenManager.Manager.GraphicsDevice.SetRenderTarget(null);
    }

    public void UnloadContent(){

    }

    public void Update(GameTime gameTime){

    }

    public void Draw(SpriteBatch SpriteBatch) {
        origin = new Vector2(SourceRect.Width / 2, SourceRect.Height /     2);
        SpriteBatch.Draw(Texture, Position + origin, SourceRect,     Color.White, 0.0f, origin, Scale, SpriteEffects.None, 0.0f);
    }

}
}

And SplashScreen class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using TEAM_TheCity.Source;

namespace EasyRPG {
public class SplashScreen : GameScreen{

    public Image Image;

    public SplashScreen () {

    }

    public override void LoadContent () {
        base.LoadContent();
        Image.LoadContent();
    }

    public override void UnloadContent () {
        base.LoadContent();
        Image.UnloadContent();
    }

    public override void Update (GameTime gameTime) {
        base.Update(gameTime);
        Image.Update(gameTime);
    }

    public override void Draw (SpriteBatch spriteBatch) {
        base.Draw(spriteBatch);
        Image.Draw(spriteBatch);
    }
}
}

GameScreen class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace EasyRPG {
public class GameScreen {

    protected ContentManager content;
    [XmlIgnore]
    public Type Type;

    public GameScreen () {
        Type = this.GetType();
    }

    public virtual void LoadContent () {
        content = new ContentManager(ScreenManager.Manager.Content.ServiceProvider, "Content");
    }

    public virtual void UnloadContent () {
        content.Unload();
    }

    public virtual void Update (GameTime gameTime) {}

    public virtual void Draw (SpriteBatch spriteBatch) {}
}
}

P.S.: sorry for that much code but I am new in XML and I have no idea what is important and what is not

Valli3
  • 153
  • 2
  • 12

2 Answers2

0

This code will work.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            SplashScreen splashScreen = new SplashScreen()
            {
                image = new Image()
                {
                    Path = "Content/splash"
                }
            };
            XmlSerializer serializer = new XmlSerializer(typeof(SplashScreen));

            StreamWriter writer = new StreamWriter(FILENAME);
            serializer.Serialize(writer, splashScreen);
            writer.Flush();
            writer.Close();
            writer.Dispose();


            XmlSerializer xs = new XmlSerializer(typeof(SplashScreen));
            XmlTextReader reader = new XmlTextReader(FILENAME);
            SplashScreen  newSplashScreen = (SplashScreen)xs.Deserialize(reader);

        }
    }
    [XmlRoot("SplashScreen")]
    public class SplashScreen
    {
        [XmlElement("Image")]
        public Image image {get; set; }

    }
    [XmlRoot("Image")]
    public class Image
    {
        [XmlElement("Path")]
        public string Path {get; set;}
    }

}
​
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • It is hard to exactly say. I believe it is the nesting of the XML serialization classes. I was confused by you saying the error occurred during serialization (classes to XML) when errors like this usually occur in de-serialization (XML to classes) and you posted the XML. How could you get the XML if the serialization failed? – jdweng Aug 10 '15 at 16:54
  • The issue is in reflecting the type, most probably because of one or more of the field types within the `Image` class. This cheats by just removing everything but `Path`. – Charles Mager Aug 10 '15 at 19:42
  • I wasn't guessing where the error was located. There is many places in the code where an exception can occur. I wasn't trying to cheat. Let the Op find out exactly where the issues are. I just provide a section of the code that I know will work. – jdweng Aug 10 '15 at 19:49
0

Here is an answer that won't change your code too much because I recognize it from a youtube tutorial and changing it too much might make it hard to follow the tutorial. You need to use [XmlIgnore] if you do not include the public variables in the Xml file. So you can either change your XMl file or add [XmlIgnore] to the image.cs Because this is from a tutorial I recommend the later, just remember to remove the added [XmlIgnore] if/when you want to add the variables to the xml file.

Best Option: Edit the Image.cs

[XmlIgnore] public float Alpha;
public string Path;
[XmlIgnore] public string Text, FontName;
[XmlIgnore] public Vector2 Position;

[XmlIgnore] public Vector2 Scale;
[XmlIgnore] public Rectangle SourceRect;

[XmlIgnore] public SpriteFont font;
[XmlIgnore] public GraphicsDevice GraphcsDevice;
[XmlIgnore] public Texture2D Texture;
Vector2 origin;

ContentManager content;
RenderTarget2D renderTarget;
[XmlIgnore] public SpriteBatch SpriteBatch;

Other Option: Edit the XML

Basically initialize all public values in XML file. (Note I left some vars out, you get the idea though)

<?xml version="1.0" encoding="utf-8" ?>
<SplashScreen>
  <Image>
    <Alpha>0.5</Alpha>
    <Path>Content/splash</Path>
    <Text>Put Text Here</Text>
    <FontName>Fonts/Orbitron</FontName>
    <Scale>
      <X>1.0</X>
      <Y>1.0</Y>
    </Scale>
    <Position>
      <X>0</X>
      <Y>0</Y>
    </Position>
    <SourceRect>Rectangle.Empty</SourceRect>
  </Image>
</SplashScreen>

Side Note

I believe that you do not need "public GraphicsDevice GraphicsDevice;" and "public SpriteBatch SpriteBatch;" in Image.cs, instead they should be in ScreenManager.cs

Also I think that "public SpriteFont font;" should not be public.