ContentSerializerRuntimeType required in content pipeline?

I have a problem at the moment loading in a texture for a larger model in the content pipeline. Now it seems that I need to make a proxy object, which is fine, however looking at the SpriteSheet example provided by Microsoft they seem to use the ContentSerializerRuntimeType attribute to bind the proxy class to the real class for use at runtime.

The problem is they sprinkle serialization attributes all over the runtime class, so I was wondering if you HAVE to do it this way or if it is just a recommendation, and is there any other way of getting your proxy class to the real instance?

Ideally I dont want to have to put attributes all over my classes and would be more than happy to write the serialization code myself if there was a way to, but it seems to be an unknown as far as the documentation goes for this area...

So anyone know a way round this, or is this just the only way to do it?

• Implement ContentTypeReader/Writer. Think you still need the COntentSerializerRuntimeType attribute. Jan 16 '12 at 8:47
• Jan 16 '12 at 8:47
• @george-duckett I thought maybe this was what I needed, but there was hardly any information on what you should be doing with a ContentTypeReader/Writer, as I presumed it would be a stage after the compile time xnb compilation and you would just take out the data and put it into your object, but it didnt seem to return any meaningful data from the methods you have to override... Will take a look at that page, I had read a few posts from Shawn's blog but I just went to where google directed me, will look through these and see if anything points me in the right direction. Jan 16 '12 at 9:15
• There are templates for implementing ContentTypeReaders/Writers in visual studio express when XNA is installed. Jan 16 '12 at 9:30
• There is? I just made a default class library and extended the classes from there. Will take a look, but an article or tutorial on the matter would go a long way to giving me and others a better understanding of these more niche/complex usages of the content pipeline. Jan 16 '12 at 9:37

If you want to avoid adding attributes to your classes (required for automatic reading/writing) then you'll want to implement a ContentTypeReader and ContentTypeWriter

Here's my runtime class that I want to load:

public class ComponentPropertyGetMathExpression : MathExpression
{
public Type ComponentType;
public string PropertyName;

public ComponentPropertyGetMathExpression()
{

}

// methods removed
}


I have 2 fields I want to get the values for.

One interesting thing here is, one of them has the type Type, which doesn't have a public parameterless constructor. You'd get weird errors if you tried to use the default reader/writer because of this, so this is a real example of when you would need to implement your own.

The first thing, is to create a Content version of this class in a seperate project, that will references the project with the runtime type and will be referenced by the content project:

[ContentSerializerRuntimeType("FuzzyDuckEntertainment.Entities.Templates.Expressions.ComponentPropertyGetMathExpression, FuzzyDuckEntertainment.Entities")]
public class ComponentPropertyGetMathExpressionContent : MathExpressionContent
{
public string ComponentType;
public string PropertyName;

public ComponentPropertyGetMathExpressionContent()
{
}

// Runtime methods not needed - this class is simply a container of fields/properties
}


The ContentSerializerRuntimeType attribute tells the pipeline what type this will represent at runtime.

Note that the ComponentType field was a Type at runtime, but here it's a string. This is because of the lack of public parameterless constructor as noted above. Another time you might have different types is when the runtime type is something GPU related, for example a Texture2D (in which case you might have ExternalReference<Texture2D> and use a ContentProcessor).

Now we have our 2 types.

I'm going to use the built in XML Importer to go from an XML file to a ComponentPropertyGetMathExpressionContent object and no Processor. A case where you might use your own importer is if you have a heightmap BMP and want to generate vertex data. An example of using a processor is the Font Texture Processor that creates a game Font from a Texture.

Now we need to get from the content type, to the runtime type.

First, lets create the class that writes the XNB file at build time:

[ContentTypeWriter]
public class ComponentPropertyGetMathExpressionContentWriter : ContentTypeWriter<ComponentPropertyGetMathExpressionContent>
{
protected override void Write(ContentWriter output, ComponentPropertyGetMathExpressionContent value)
{
output.Write(value.ComponentType);
output.Write(value.PropertyName);
}

{
}

public override string GetRuntimeType(TargetPlatform targetPlatform)
{
return typeof(ComponentPropertyGetMathExpression).AssemblyQualifiedName;
}
}


Hopefully the above should be self explanatory (note the order we write the fields in).

The reader is implemented as below:

public class ComponentPropertyGetMathExpressionReader : ContentTypeReader<ComponentPropertyGetMathExpression>
{
{
if (existingInstance == null)
existingInstance = new ComponentPropertyGetMathExpression();


Note the order we read things in. Also note that the first thing we read is the string that correspond to the ComponentType property. As the runtime type in this case is Type, not string I need to do some simple translation. Ideally you want any translations like this to be as minimal as possible, as unlike anything before, this will run when the game is loading.