Способы установки 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;
}
}
}
-
измените класс 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));
достигнет желаемого поведения, не имея публичного конструктора, но позволяя эффективно вводить ваш фасад.
-
выполните впрыску каждый раз
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();
этой суть есть полный рабочий пример выше подход.
надеюсь, что это поможет!