Ninject: синтаксис привязки синглтона? - PullRequest
9 голосов
/ 06 апреля 2010

Я использую Ninject 2.0 для .Net 3.5 framework. У меня проблемы с привязкой синглтона.

У меня есть класс UserInputReader, который реализует IInputReader. Я хочу, чтобы когда-либо был создан только один экземпляр этого класса.

 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;
        }
}

Если я сделаю этот конструктор приватным, он сломается. Что я тут не так делаю?

Ответы [ 2 ]

18 голосов
/ 06 апреля 2010

Конечно, это сломается, если вы сделаете конструктор приватным. Вы не можете вызывать частных конструкторов за пределами вашего класса!

То, что вы делаете, это именно то, что вы должны делать. Проверьте это:

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

Вам не нужно статическое поле, чтобы получить экземпляр синглтона. Если вы используете контейнер IoC, вы должны получить все свои экземпляры через контейнер.

Если вы делаете хотите открытое статическое поле (не уверены, есть ли для этого веские причины), вы можете привязать тип к его значению, например:

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

РЕДАКТИРОВАТЬ : Чтобы указать IDictionary<ActionInputType, Keys> для использования в конструкторе UserInputReader, вы можете использовать метод WithConstructorArgument:

Bind<UserInputReader>().ToSelf()
     .WithConstructorArgument("keyMapping", Constants.DEFAULT_KEY_MAPPING)
     .InSingletonScope();
0 голосов
/ 06 апреля 2010

IInputReader не объявляет поле Instance и не может его делать, поскольку интерфейсы не могут иметь поле или статическое поле, или даже статические свойства (или статические методы).

Класс Bind может не знать, что он должен найти поле Instance (если он не использует отражение).

...