#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using Ninject; using Ninject.Activation; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using XnaGame = Microsoft.Xna.Framework.Game; namespace Nuclex.Ninject.Xna { /// Ninject-based XNA game public class NinjectGame : XnaGame, IGame, IGameInitializer { /// Called when the game has begun the second stage initialization public event EventHandler Initializing; /// Initializes a new ninject-based XNA game /// /// Kernel the dependency-injected components are managed in /// public NinjectGame(IKernel kernel) { // // We register all services provided by the game here (and not through // method bindings that forward to the game class) because otherwise, // if the Game class ever tried to create a component through Ninject // that depended on the Game class again, this would not be resolvable // by Ninject (as it's already trying to construct a game at that time) // // All components are registered as 'singletons' to the kernel managing // the game. This does not prevent you from setting up another kernel // that does something entirely else, but for all purposes, having more // than one XNA game active in the same process at the same time does // not make much sense ;-) // // The game automatically creates a content manager as well. Through // this binding, all components can access this content manager to // store and retrieve any game-global content. kernel.Rebind().ToConstant(Content).InSingletonScope(); // Bind XNA's service container (which is another IServiceProvider) to // Ninject. Some game components will pull their dependencies exclusively // from here, so components should be able to add themselves to it. kernel.Rebind().ToConstant(Services).InSingletonScope(); kernel.Rebind().ToConstant(Services).InSingletonScope(); // By adding themselves to this collection, components can take part in // the game's update and redraw cycles. kernel.Rebind().ToConstant(Components).InSingletonScope(); // The graphics device service is probably the most important service // for an XNA game, but XNA also leaves open the possibility of a Game // not actually using the graphics device service at all, so we go through // the GameServiceContainer, where it will register itself if it is created. kernel.Rebind().ToMethod( getGraphicsDeviceService ).InSingletonScope(); kernel.Rebind().ToMethod( getGraphicsDeviceManager ).InSingletonScope(); // This binding should not be used normally. Components should access // the graphics device manager through the IGraphicsDeviceService interface. // Some existing components, like Sunburn's LightingSystemEditor, however, // ask for the GraphicsDeviceManager itself, so this allows such components // to be activated by attempting to downcast whatever component implements // the IGraphicsDeviceManager service. kernel.Rebind().ToMethod( getConcreteGraphicsDeviceManager ).InSingletonScope(); } /// /// Called after all components are initialized but before the first update in /// the game loop. /// protected override void Initialize() { // Do not call base.Initialize() first here. It might seem to make more sense // (initialize base before derived), but the way XNA's startup works, doing it // the other way around will cause any game components added during this phase // to not be initialized at all (they will be placed on the notYetInitialized // list because inRun is still false, but the notYetInitialized list has already // been processed at this time). OnInitializing(); base.Initialize(); } /// Fires the Initializing event protected virtual void OnInitializing() { if(Initializing != null) { Initializing(this, EventArgs.Empty); } } /// /// Looks up the graphics device service from the game's registered /// service providers /// /// /// Context containing the kernel and informations about the request /// /// The graphics device service /// /// Thrown if the game has not created a graphics device manager /// private static IGraphicsDeviceService getGraphicsDeviceService(IContext context) { var services = context.Kernel.GetService(); // Look up the game's graphics device service and display and bail out // with a sane error message if the game does not provide that service. IGraphicsDeviceService graphicsDeviceService; if (!services.TryGetService(out graphicsDeviceService)) { throw new ActivationException( "No active graphics device service is registered for the game" ); } return graphicsDeviceService; } /// /// Looks up the graphics device manager from the game's registered /// service providers /// /// /// Context containing the kernel and informations about the request /// /// The graphics device manager /// /// Thrown if the game has not created a graphics device manager /// private static IGraphicsDeviceManager getGraphicsDeviceManager(IContext context) { var services = context.Kernel.GetService(); // Look up the game's graphics device service and display and bail out // with a sane error message if the game does not provide that service. IGraphicsDeviceManager graphicsDeviceManager; if (!services.TryGetService(out graphicsDeviceManager)) { throw new ActivationException( "No active graphics device manager is registered for the game" ); } return graphicsDeviceManager; } /// /// Looks up the actual graphics device manager implementation class. /// Should not be used under normal circumstances. /// /// /// Context containing the kernel and informations about the request /// /// The XNA graphics device manager instance private static GraphicsDeviceManager getConcreteGraphicsDeviceManager(IContext context) { var graphicsDeviceManager = getGraphicsDeviceManager(context); var concrete = graphicsDeviceManager as GraphicsDeviceManager; if(concrete == null) { throw new ActivationException( "Cannot access GraphicsDeviceManager because the game's IGraphicsDeviceManager " + "service is provided by a custom component" ); } return concrete; } } } // namespace Nuclex.Ninject.Xna