Ninject: Singleton обязательный синтаксис?

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

У меня есть класс 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;
        }
}

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

9
задан Nick Heiner 5 April 2010 в 22:19
поделиться

2 ответа

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

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

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

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

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

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

EDIT : Чтобы указать IDictionary для использования в конструкторе UserInputReader , вы можете использовать метод WithConstructorArgument :

Bind<UserInputReader>().ToSelf()
     .WithConstructorArgument("keyMapping", Constants.DEFAULT_KEY_MAPPING)
     .InSingletonScope();
18
ответ дан 4 December 2019 в 11:41
поделиться

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

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

0
ответ дан 4 December 2019 в 11:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: