Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject: Singleton binding syntax?

I'm using Ninject 2.0 for the .Net 3.5 framework. I'm having difficulty with singleton binding.

I have a class UserInputReader which implements IInputReader. I only want one instance of this class to ever be created.

 public class MasterEngineModule : NinjectModule
    {
        public override void Load()
        {
            // using this line and not the other two makes it work
            //Bind<IInputReader>().ToMethod(context => new UserInputReader(Constants.DEFAULT_KEY_MAPPING));

            Bind<IInputReader>().To<UserInputReader>();
            Bind<UserInputReader>().ToSelf().InSingletonScope();
        }
    }

        static void Main(string[] args) 
        {
            IKernel ninject = new StandardKernel(new MasterEngineModule());
            MasterEngine game = ninject.Get<MasterEngine>();
            game.Run();
        }

 public sealed class UserInputReader : IInputReader
    {
        public static readonly IInputReader Instance = new UserInputReader(Constants.DEFAULT_KEY_MAPPING);

        // ...

        public UserInputReader(IDictionary<ActionInputType, Keys> keyMapping)
        {
            this.keyMapping = keyMapping;
        }
}

If I make that constructor private, it breaks. What am I doing wrong here?

like image 540
Nick Heiner Avatar asked Apr 05 '10 22:04

Nick Heiner


1 Answers

Of course it breaks if you make the constructor private. You can't call private constructors from outside your class!

What you're doing is exactly what you're supposed to do. Test it:

var reader1 = ninject.Get<IInputReader>();
var reader2 = ninject.Get<IInputReader>();
Assert.AreSame(reader1, reader2);

You don't need the static field to get the instance singleton. If you're using an IoC container, you should get all your instances through the container.

If you do want the public static field (not sure if there is a good reason for that), you can bind the type to its value, like this:

Bind<UserInputReader>().ToConstant(UserInputReader.Instance);

EDIT: To specify the IDictionary<ActionInputType, Keys> to use in the constructor of UserInputReader, you can use the WithConstructorArgument method:

Bind<UserInputReader>().ToSelf()
     .WithConstructorArgument("keyMapping", Constants.DEFAULT_KEY_MAPPING)
     .InSingletonScope();
like image 198
R. Martinho Fernandes Avatar answered Oct 23 '22 01:10

R. Martinho Fernandes