Способы установки Ninject синглтон

у меня есть класс (MyFacade), которую я ввел параметр(ы) с Ninject:

class MyFacade
{
    IDemoInterface demo;

    public MyFacade(IDemoInterface demo)
    {
        this.demo = demo;
    }

    public void MyMethod()
    {
        Console.WriteLine(demo.GetInfo());
    }
} 

конечно, я должен настроить Ninject чтобы ввести соответствующую реализацию моего параметра (IDemoInterface)

Я знаю, я могу создать экземпляр

2 ответов


при настройке Привязок необходимо привязать зависимости. Всегда лучше настроить свои зависимости в привязках, а не делать kernel.Get<T>() в конструктор. Вы используете МОК, поэтому используйте структуру, которую вы используете, чтобы сделать инъекцию для вас.

во втором примере привязки, то, что вам не хватает привязки в вашем IDemoInterface. Привязки должны выглядеть так:

//bind the dependency to the implementation.
kernel.Bind<IDemoInterface>().To<DemoInterface>();
//since you bound your dependency, ninject should now have 
// all the dependencies required to instantiate your `MyFacade` object.
kernel.Bind<MyFacade>.To<MyFacade>().InSingletonScope(); 

если вы не хотите, чтобы контейнер для управления жизненным циклом синглтон с помощью InSingletonScope(), но все же хочет, чтобы его ввели, я могу придумать 2 способа сделать это. Выберите, какой из них лучше подходит для ваших нужд. Рассмотрим следующее ISingleton (назовите свой интерфейс) реализация:

public class ConcreteSingleton : ISingleton
{
    private static readonly Lazy<ConcreteSingleton> _instance = new Lazy<ConcreteSingleton>(() => new ConcreteSingleton());

    private ConcreteSingleton() { }

    public static ConcreteSingleton Instance
    {
        get
        {
            return _instance.Value;
        }
    }
}
  1. измените класс singleton, чтобы иметь GetInstance(...) метод

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

    public static ConcreteSingleton GetInstance(IKernel kernelForInjection)
    {
        if (_instance.IsValueCreated == false)
        {
            kernelForInjection.Inject(_instance.Value);
        }
    
        return _instance.Value;
    }
    

    и используя эту привязку:

    kernel.Bind<ISingleton>().ToMethod(c => ConcreteSingleton.GetInstance(c.Kernel));
    

    достигнет желаемого поведения, не имея публичного конструктора, но позволяя эффективно вводить ваш фасад.

  2. выполните впрыску каждый раз ISingleton экземпляр запрошено

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

    internal class ConcreteSingletonProvider : Provider<ISingleton>
    {
        public IKernel Kernel { get; set; }
    
        //Just a wrapper
        private readonly Lazy<ISingleton> _lazy = new Lazy<ISingleton>(() => ConcreteSingleton.Instance);
    
        public ConcreteSingletonProvider(IKernel kernel)
        {
            Kernel = kernel;
        }
    
        protected override ISingleton CreateInstance(IContext context)
        {
            if (_lazy.IsValueCreated == false)
            {
                Kernel.Inject(ConcreteSingleton.Instance);
            }
            return _lazy.Value;
        }
    }
    

    и ваши привязки должны быть такими:

    kernel.Bind<ISingleton>().ToProvider<ConcreteSingletonProvider>();
    kernel.Bind<ConcreteSingletonProvider>().ToSelf().InSingletonScope();
    

    этой суть есть полный рабочий пример выше подход.

надеюсь, что это поможет!