That's what I always thought, until I realised the true purpose and capability of game "services", and their link to boxing/unboxing and the .Net type system.
One fault I will admit Microsoft have is their lack of creative naming. At first I always thought game services were linked to system services or that services were some sort of special class or interface.
In fact, a game's services collection is nothing more than a collection of objects. What the services allow is for any game components that have been hooked up to the game to retrieve data from the game.
One example of this is the SpriteBatch. By adding a SpriteBatch to the game's services, and registering it with typeof(SpriteBatch), any component can then extract that SpriteBatch from the services by feeding typeof(SpriteBatch) to the GetService method.
Below is some sample code (not tested, just an example):
public namespace MyGame
{
public class MainGame:Game
{
SpriteBatch spriteBatch;
protected override void Initialize()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Services.AddService(typeof(SpriteBatch), spriteBatch);
base.Initialize();
}
}
public class DrawableComponent : DrawableGameComponent
{
SpriteBatch spriteBatch;
public override void Initialize()
{
spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
if(spriteBatch == null)
{ throw new Exception("No SpriteBatch found in services"); }
}
}
}
My example here also demonstrates a very overlooked factor.
Microsoft's default game template places the SpriteBatch creation in the load content method, leading many to believe is must remain there. In fact, you are free shift it much further forward, up as far as the initialisation method (but not the constructor), meaning it can be shifted into the services before any components are initialised, thus ensuring all components that seek a SpriteBatch from the services in their initialisation method will get one.
Make sure to note that while adding to the services will throw an exception if a given item is null, taking from them will not, it will simply return null and carry on executing, thus null checking must be performed asap. Also note that if a component is created mid game, it won't have its initialisation called, so this must be compensated for by some means.
Further examples of this technique can be found here: http://itspaulsblog.blogspot.co.uk/2011/02/xna-common-sprite-batch-as-game-service.html