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;
// 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:
public class ComponentPropertyGetMathExpressionContent : MathExpressionContent
public string ComponentType;
public string PropertyName;
// 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:
public class ComponentPropertyGetMathExpressionContentWriter : ContentTypeWriter<ComponentPropertyGetMathExpressionContent>
protected override void Write(ContentWriter output, ComponentPropertyGetMathExpressionContent value)
public override string GetRuntimeReader(TargetPlatform targetPlatform)
public override string GetRuntimeType(TargetPlatform targetPlatform)
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>
protected override ComponentPropertyGetMathExpression Read(ContentReader input, ComponentPropertyGetMathExpression existingInstance)
if (existingInstance == null)
existingInstance = new ComponentPropertyGetMathExpression();
existingInstance.ComponentType = Type.GetType(input.ReadString());
existingInstance.PropertyName = input.ReadString();
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
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.
What Is Content? (MSDN)
Using an XML File to Specify Content (MSDN)
Shawn Hargreaves' Blog Index #Content Pipeline