Roy Triesscheijn’s Weblog

My programming world

XNA: Accessing ContentManager and GraphicsDevice anywhere anytime, the GameServiceContainer

Posted by Roy Triesscheijn on August 25th, 2010

A quick code snippet that I produced today and wanted to share.

Often you find yourself looking for a good path/way to give a certain component access to the ContentManager. Usually you will just plug it in the construct. However sometimes the object creating the new object doesn’t have access to this component as well. Things start to become a bit more complicated then, of course you can add it to both constructors, but things often start to clutter.

Objects like the ContentManager and the GraphicsDevice are often needed on the craziest of places in a game’s code. They can easily be shared as they are usually in a valid state throughout the runtime of your program and usually you don’t need more than one. For these kind of objects it would be easy to create a static class so that anyone can access them.

A common technique is to create a static List in which you can throw anything in. But this doesn’t enforce that there is only instance of a given type in the container (why add two GraphicsDevices?) and makes it hard to get the right component from.

Luckily XNA has the GameServiceContainer class which allows you to store elements like this:

container = GameServicesContainer();
container.AddService(typeof(GraphicsDevice), device);

There’s also GetService and RemoveService. However this casting can make a lot of lines way longer than they need to be. Also we need to make the container static and protected access to it, so let’s create a nice little class like this:

public static class GameServices
    {
        private static GameServiceContainer container;
        public static GameServiceContainer Instance {
            get
            {
                if (container == null)
                {
                    container = new GameServiceContainer();
                }
                return container;
            }
        }

        public static T GetService<T>()
        {
            return (T)Instance.GetService(typeof(T));
        }

        public static void AddService<T>(T service)
        {
            Instance.AddService(typeof(T), service);
        }

        public static void RemoveService<T>()
        {
            Instance.RemoveService(typeof(T));
        }
    }

In the Initialize method of Gam1.cs put this:

protected override void Initialize()
        {
            base.Initialize();
            GameServices.AddService<GraphicsDevice>(GraphicsDevice);
            GameServices.AddService<ContentManager>(Content);
        }

Remember that GameServices is static so you can read, add and remove from anywhere in your code like this:

GameServices.AddService<GraphicsDevice>(device);
myDevice = GameServices.GetService<GraphicsDevice>();
GameServices.RemoveService<GraphicsDevice>()

Quite a nifty way of doing this, if I may say that myself (A). However do note (as NullSoldi did on Efnet #xna) that this will increase coupling between your components as some class will start to depend on the non standard class we’ve just created while this otherwise wasn’t needed. However I personally think that the benefits greatly outweigh the small penalty on coupling.

Have fun with this snippet, let me know if you’re using it or found it useful for your own GameServices-like class.

5 Responses to “XNA: Accessing ContentManager and GraphicsDevice anywhere anytime, the GameServiceContainer”

  1. Tyler Says:

    I find it very interesting. I think this idea has many possibilities. I congratulate you, thank you for your idea.
    Greetings.

  2. Brandon Says:

    Great idea…. even better is the fact that I came up with the same idea, great minds think alike! I don’t understand why the Service containers GetService method doesn’t do the casting for you… or provide both ways and allow the programmer to chose which to use.

    Instead of creating my own GameServices class, I simply created a GameEngine class, which inherits XNA’s Game class, and put the static GetService() method and GameServicesContainer field within the GameEngine class. The GameEngine constructor simply assigns the static field and voila.

    Your main() function simply needs to be changed to the following:

    using (Game game = new GameEngine())
    {
    game.Run();
    }

    To retrieve services, the code is now simply:

    GameEngine.GetService();

    It feels more intuitive this way. This can also be done with the ContentManager, GraphicsDeviceManager, GameWindow, Spritebatch

  3. Roy Triesscheijn Says:

    Hey Brandon, the GetService call actually does casting for you: return (T)Instance.GetService(typeof(T)); as you see it casts to T. And puting the active part inside a new GameEngine class is a good idea, however as a code snippet it wouldn’t be as portable as it is now :) .

  4. Brandon Says:

    good point with the snippet!

    I see that your codedoes indeed do the type casting. But what I was wondering is why the XNA services container doesn’t already provide this feature without requiring us to make these handy snippets. It feels as if we were given the correct tool for the job… only a couple of sizes too small.

  5. Roy Triesscheijn Says:

    Well I think the GameServiceContainer is used by the Game class by default (something like Game.Services) but I don’t believe it’s static, so then you need a reference to Game in every class.





Or leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>