簡體   English   中英

如何在XNA中使用Ninject?

[英]How to use Ninject with XNA?

我在將Ninject與XNA集成時遇到困難。

static class Program
{
    /**
     * The main entry point for the application.
     */
    static void Main(string[] args) 
    {
        IKernel kernel = new StandardKernel(NinjectModuleManager.GetModules());
        CachedContentLoader content = kernel.Get<CachedContentLoader>(); // stack overflow here
        MasterEngine game = kernel.Get<MasterEngine>();
        game.Run();
    }
}

    // constructor for the game
    public MasterEngine(IKernel kernel)
        : base(kernel)
    {
        this.inputReader = kernel.Get<IInputReader>();

        graphicsDeviceManager = kernel.Get<GraphicsDeviceManager>();
        Components.Add(kernel.Get<GamerServicesComponent>());

        // Tell the loader to look for all files relative to the "Content" directory.
        Assets = kernel.Get<CachedContentLoader>();

        //Sets dimensions of the game window
        graphicsDeviceManager.PreferredBackBufferWidth = 800;
        graphicsDeviceManager.PreferredBackBufferHeight = 600;
        graphicsDeviceManager.ApplyChanges();

        IsMouseVisible = false;
    }

Ninject.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject.Modules;
using HWAlphaRelease.Controller;
using Microsoft.Xna.Framework;
using Nuclex.DependencyInjection.Demo.Scaffolding;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace HWAlphaRelease
{
    public static class NinjectModuleManager
    {

        public static NinjectModule[] GetModules()
        {
            return new NinjectModule[1] { new GameModule() };
        }

        /// <summary>Dependency injection rules for the main game instance</summary>
        public class GameModule : NinjectModule
        {

            #region class ServiceProviderAdapter

            /// <summary>Delegates to the game's built-in service provider</summary>
            /// <remarks>
            ///   <para>
            ///     When a class' constructor requires an IServiceProvider, the dependency
            ///     injector cannot just construct a new one and wouldn't know that it has
            ///     to create an instance of the Game class (or take it from the existing
            ///     Game instance).
            ///   </para>
            ///   <para>
            ///     The solution, then, is this small adapter that takes a Game instance
            ///     and acts as if it was a freely constructable IServiceProvider implementation
            ///     while in reality, it delegates all lookups to the Game's service container.
            ///   </para>
            /// </remarks>
            private class ServiceProviderAdapter : IServiceProvider
            {

                /// <summary>Initializes a new service provider adapter for the game</summary>
                /// <param name="game">Game the service provider will be taken from</param>
                public ServiceProviderAdapter(Game game)
                {
                    this.gameServices = game.Services;
                }

                /// <summary>Retrieves a service from the game service container</summary>
                /// <param name="serviceType">Type of the service that will be retrieved</param>
                /// <returns>The service that has been requested</returns>
                public object GetService(Type serviceType)
                {
                    return this.gameServices;
                }

                /// <summary>Game services container of the Game instance</summary>
                private GameServiceContainer gameServices;

            }

            #endregion // class ServiceProviderAdapter

            #region class ContentManagerAdapter

            /// <summary>Delegates to the game's built-in ContentManager</summary>
            /// <remarks>
            ///   This provides shared access to the game's ContentManager. A dependency
            ///   injected class only needs to require the ISharedContentService in its
            ///   constructor and the dependency injector will automatically resolve it
            ///   to this adapter, which delegates to the Game's built-in content manager.
            /// </remarks>
            private class ContentManagerAdapter : ISharedContentService
            {

                /// <summary>Initializes a new shared content manager adapter</summary>
                /// <param name="game">Game the content manager will be taken from</param>
                public ContentManagerAdapter(Game game)
                {
                    this.contentManager = game.Content;
                }

                /// <summary>Loads or accesses shared game content</summary>
                /// <typeparam name="AssetType">Type of the asset to be loaded or accessed</typeparam>
                /// <param name="assetName">Path and name of the requested asset</param>
                /// <returns>The requested asset from the the shared game content store</returns>
                public AssetType Load<AssetType>(string assetName)
                {
                    return this.contentManager.Load<AssetType>(assetName);
                }

                /// <summary>The content manager this instance delegates to</summary>
                private ContentManager contentManager;

            }

            #endregion // class ContentManagerAdapter

            /// <summary>Initializes the dependency configuration</summary>
            public override void Load()
            {

                // Allows access to the game class for any components with a dependency
                // on the 'Game' or 'DependencyInjectionGame' classes.
                Bind<MasterEngine>().ToSelf().InSingletonScope();
                Bind<NinjectGame>().To<MasterEngine>().InSingletonScope();
                Bind<Game>().To<MasterEngine>().InSingletonScope();

                // Let the dependency injector construct a graphics device manager for
                // all components depending on the IGraphicsDeviceService and
                // IGraphicsDeviceManager interfaces
                Bind<GraphicsDeviceManager>().ToSelf().InSingletonScope();
                Bind<IGraphicsDeviceService>().To<GraphicsDeviceManager>().InSingletonScope();
                Bind<IGraphicsDeviceManager>().To<GraphicsDeviceManager>().InSingletonScope();

                // Some clever adapters that hand out the Game's IServiceProvider and allow
                // access to its built-in ContentManager
                Bind<IServiceProvider>().To<ServiceProviderAdapter>().InSingletonScope();
                Bind<ISharedContentService>().To<ContentManagerAdapter>().InSingletonScope();

                Bind<IInputReader>().To<UserInputReader>().InSingletonScope().WithConstructorArgument("keyMapping", Constants.DEFAULT_KEY_MAPPING);
                Bind<CachedContentLoader>().ToSelf().InSingletonScope().WithConstructorArgument("rootDir", "Content");

            }

        }

    }

}

NinjectGame.cs

  /// <summary>Base class for Games making use of Ninject</summary>
  public class NinjectGame : Game {

    /// <summary>Initializes a new Ninject game instance</summary>
    /// <param name="kernel">Kernel the game has been created by</param>
    public NinjectGame(IKernel kernel) {
      Type ownType = this.GetType();

      if(ownType != typeof(Game)) {
        kernel.Bind<NinjectGame>().To<MasterEngine>().InSingletonScope();
      }

        kernel.Bind<Game>().To<NinjectGame>().InSingletonScope();
    }

  }

} // namespace Nuclex.DependencyInjection.Demo.Scaffolding

當我嘗試獲取CachedContentLoader ,出現堆棧溢出異常。 我以本教程為基礎 ,但是我真的不知道自己在做什么。 救命?

您可能在已配置的依賴項之一中具有循環引用。 因此,當ninject嘗試實例化所討論的類時,它將陷入無限循環的注入。

我沒有仔細檢查您的類以了解它的含義,但建議您在GameModule.Load中定義的每個類的構造函數中放置一個斷點。 一旦您看到嵌套實例化發生的位置,它就會變得很明顯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM