4
\$\begingroup\$

I made a program that simulates an assembly line using the XNA 4.0. I made a 3D model, and divided it into 5 positions - start, 3 workstations, and end. These positions represent the places on the model that (in real life) would be covered by some type of sensors. Whenever an object gets to one of these positions, it triggers a method that is binded to that specific position (like "Stop", "Start", "Increment/Decrement Counter"...).

This program has to be able to load a file that describes the behavior of the entire assembly line - meaning, this file has to tell the program when and which method will be triggered (for now it is only Start/Stop methods). To do this, I created a method that serializes the class that contains bool variables (these variables determine if the position will be "active" or not - if the value is true then the object will trigger the binded method, if it is false then it will simply pass that position, without any additional actions being performed).

This is the problem I'm having: My method successfully serializes the class, and creates the .xml file, but if I load this file as Content, it gives me the following error "There was an error while deserializing intermediate XML. Cannot find type "Postavke.PostavkeStanice"."

This is the code of my class:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;
using System.Xml;
namespace Postavke
{

    public class PostavkeStanice
    {
        public bool radnaStanica1_Stanje;
        public bool radnaStanica2_Stanje;
        public bool radnaStanica3_Stanje;
        public bool kraj_Stanje;
        MemoryStream ms = new MemoryStream();
        public void ClassToXML()
        {

          XmlTextWriter pisac = new XmlTextWriter(ms, Encoding.UTF8);
          pisac.Formatting = Formatting.Indented;
          IntermediateSerializer.Serialize(pisac, this, "Postavke.xml");            
        }

        public string XMLToXNA()
        {
            ms.Seek(0, SeekOrigin.Begin);
            TextReader citac = new StreamReader(ms);
            return citac.ReadToEnd();
        }
    }
}

Since this class is a part of Game Library, I set the dependencies so that the Game library gets compiled before the main project. When I run the code I get the fore mentioned error. Can you tell me what I'm doing wrong Thank you

\$\endgroup\$
2
  • \$\begingroup\$ This example uses XML for data import: create.msdn.com/en-US/education/catalog/sample/roleplaying_game Fora šta si ostavio nazive varijabli na hrvatski ;) \$\endgroup\$ Commented Jan 17, 2012 at 7:33
  • \$\begingroup\$ Hahahha pa ovo je projekt za fakultet (profesor je predložio projekt, ja sam predložio način izvedbe) tako da će sve varijable i biti na hrvatskom, osim onih koje XNA elementi koriste (kao projection, world i takve) :D \$\endgroup\$
    – NDraskovic
    Commented Jan 17, 2012 at 9:05

2 Answers 2

2
\$\begingroup\$

Typically you would use the content pipeline to do this automatically. See Customizing the IntermediateSerializer.

Create a library project that has your type in it (with no serialize/deserialise methods). Add a reference to it in the content project and your game project. Add an XML file to your content project in the appropriate format then load it in game with

Content.Load<PostavkeStanice>(RelativeXMLLocationWithoutExtension).

See also for an example where the pipeline is customized: ContentSerializerRuntimeType required in content pipeline?


The below also might be a solution to your problem, it's certainly a better solution to the problem that the existing answer solves.


Somewhere in your class and it's properties/fields there's a type with no parameterless constructor. Probably a member of the MemoryStream class.

To serialize any object it instantiates it by finding a parameterless constructor and invoking it via reflection.

The new security model is stopping it from invoking the non-public parameterless constructor via reflection and is causing the error you're seeing.

As the other answer says, changing your application's security will solve the issue but will have other ramifications, particularly if you use different libraries, or have other classes that use your library.

Add the [ContentSerializerIgnore] attribute on ones you want it to ignore (like the MemoryStream) and add public parameterless constructors to all classes that are to be serialized (and classes of fields/properties).

\$\endgroup\$
7
  • \$\begingroup\$ Also, if you only want to edit the values at built time the pipeline can do this for you (without the (de)serialise methods). \$\endgroup\$ Commented Jan 17, 2012 at 8:00
  • \$\begingroup\$ See: Customizing the IntermediateSerializer \$\endgroup\$ Commented Jan 17, 2012 at 8:01
  • \$\begingroup\$ I tried the first solution you proposed, it gave me the same error (I also tried to change from Postavke.PostavkeStanice to System.Boolean, then it throws an error "XML does not have enough entries in space-separated list"). Is it possible to make a method that will read a single element in XML file (for <radnaStanica1>true</radnaStanica1> to return true, as string or boolean). Since my .xml file has permanent structure, the same elements will always be in the same place - so is there a way to make a method that will read only one element? \$\endgroup\$
    – NDraskovic
    Commented Jan 17, 2012 at 10:47
  • \$\begingroup\$ You could use standard .net to read an XML file. Maybe post that question in stackoverflow. See the example XML in the Customizing the IntermediateSerializer for what an XML file that's going to be read should look like. \$\endgroup\$ Commented Jan 17, 2012 at 10:59
  • \$\begingroup\$ I managed to solve the problem, and it was probably the basic beginners overlook on my part. I referenced my Game library in my main project, but not in my Content project (I thought they were one project). It works now when I rebuild, I'll see if it works when I publish the program. Thanks for your help \$\endgroup\$
    – NDraskovic
    Commented Jan 17, 2012 at 11:23
1
\$\begingroup\$

Try putting the below above your namespace.

[assembly: SecurityTransparent] 

http://www.simple-talk.com/dotnet/.net-framework/whats-new-in-code-access-security-in-.net-framework-4.0---part-i/

http://www.simple-talk.com/dotnet/.net-framework/whats-new-in-code-access-security-in-.net-framework-4.0---part-2/

\$\endgroup\$
3
  • \$\begingroup\$ While that will work, it's not the recommended solution and is just a workaround really. \$\endgroup\$ Commented Jan 17, 2012 at 7:59
  • \$\begingroup\$ And i'm not sure that is the problem. \$\endgroup\$ Commented Jan 17, 2012 at 8:09
  • \$\begingroup\$ No, it didn't work \$\endgroup\$
    – NDraskovic
    Commented Jan 17, 2012 at 10:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .