Custom XML content importers and Shared Projects

I started a new project recently, where I wanted to create a game engine, along with a game using it. I created a shared project for the engine, and referenced it in the game project. I used the shared project as I would like to share this code in multiple, cross-platform projects. Maybe this was not the best option, I am new to Monogame and C#/Visual Studio in general.

Anyway, in doing this I created a class describing the XML content. Then created a sample XML file
<?xml version="1.0" encoding="utf-8" ?> <XnaContent> <Asset Type="AdventureEngine.DataManager.GameStartDescription"> <StartingScreen>FirstScreen</StartingScreen> </Asset> </XnaContent>

but when I tried to build the content pipeline I got an error:

C:/Development/Monogame/Projects/AdventureTest/AdventureTest/Content/StartGameDescription.xml: error: Importer ‘XmlImporter’ had unexpected failure!
Microsoft.Xna.Framework.Content.Pipeline.InvalidContentException: Could not resolve type ‘AdventureEngine.DataManager.GameStartDescription’.
at Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate.IntermediateReader.ReadObject[T](ContentSerializerAttribute format, ContentTypeSerializer typeSerializer, T existingInstance)
at Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate.IntermediateReader.ReadObject[T](ContentSerializerAttribute format)
at Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate.IntermediateSerializer.Deserialize[T](XmlReader input, String referenceRelocationPath)
at Microsoft.Xna.Framework.Content.Pipeline.XmlImporter.Import(String filename, ContentImporterContext context)
at Microsoft.Xna.Framework.Content.Pipeline.ContentImporter`1.Microsoft.Xna.Framework.Content.Pipeline.IContentImporter.Import(String filename, ContentImporterContext context)
at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.ProcessContent(PipelineBuildEvent pipelineEvent)

and it clearly cannot find class in the shared project. I found some tutorials that indicate I have to create a library, and reference it in the content pipeline. Is it possible to do this another way? Can I reference a shared project somehow?

Did you add a reference to the shared project in the MGCB file? Load the MGCB file in the Pipeline tool, select the root node and in the Properties window, edit the References property to add the location of the DLL for the shared project. You should then be able to build the content.

A shared project does not produce a dll, at least that is what I thought was the case. The shared code is compiled into the assembly created by the project that references the shared code.

Basically, I was wondering if there is some other way to add a reference to the MGCB file, that does not rely on having a dll to reference. When I created the game project, and shared project, I did not realize that the MGCB file, while in a project that references the shared project, is unaware of it.

I don’t understand this new shared project thing. I’ve never looked into it.

The code declaring the class used in the asset XML needs to be available to both the game and the content builder as a DLL that is referenced by both.

If I rework it, and create a class library, then I should be able to use it? I’ll give it a try at least. I’d like to keep the engine code separate from the game as I would like to reuse it in other projects. Or should I create a portal class library? I want to be able to make cross platform games.

A portable class library should work, otherwise just a regular class library.

@Travis_Stewart my advice is to split out the bits that the content Pipeline will use into a PCL. There is a PCL version of MonoGame in Nuget that you can reference in “Pre-release” .

That said I personally LOVE shared projects for game code :slight_smile: So what you could also do is this…

Keep the shared project and just add a PCL/Normal library that uses it, this will be just for the pipeline.

Keep in mind you will need to be careful of your assembly names etc. Allot of the templates tag on a to the end of the assembly (e.g AdventureEngine.iOS AdventureEngine.Android). If you don’t change those platforms to emit a “AdventureEngine” assembly/exe then the type lookup will probably fail at run time.

Thanks for the advice. I will keep that in mind. I went with a regular class library for now, which is not as convenient for cross platform support, but I may look into PCL in the future, or the mixed shared project/PCL route. When I looked on Nuget the newest PCL version was 3.2, which I suppose I could use but I thought I might wait and read and see if an updated version is released.

The MonoGame PCL is just a Facade assembly which has no implementation. So 3.2 will still be compatible (we didn’t change the API). It gets replaced with the platform specific assemblies at build time :slight_smile: