Обновление: уверен, что использование множественных перегрузок Bind V3 решит эту проблему; См. это Q / A
Хороший вопрос.
При просмотре источника бит инициализации происходит после каждого Activate
. Ваш Bind...ToMethod
тоже считается одним. Стратегия применяется довольно единообразно - в определенных случаях нет возможности отказаться.
Ваши варианты обходного пути - использовать явный OnActivation
в вашем Bind
, который будет делать это условно (но для того, чтобы сделать это в общем случае, потребуется поддержка набора инициализированных объектов (не смотрел, чтобы увидеть, есть ли механизм для того, чтобы спрятать флаг против активированного объекта)), или сделать ваш инициализированный идемпотент любыми способами, которые наиболее чисты для вас.
EDIT:
internal interface IService1
{
}
internal interface IService2
{
}
public class ConcreteService : IService1, IService2, Ninject.IInitializable
{
public int CallCount { get; private set; }
public void Initialize()
{
++CallCount;
}
}
public class ServiceModule : NinjectModule
{
public override void Load()
{
this.Singleton<IService1, IService2, ConcreteService>();
}
}
Имеются следующие помощники:
static class Helpers
{
public static void Singleton<K, T>( this NinjectModule module ) where T : K
{
module.Bind<K>().To<T>().InSingletonScope();
}
public static void Singleton<K, L, T>( this NinjectModule module )
where T : K, L
{
Singleton<T, T>( module );
module.Bind<K>().ToMethod( n => n.Kernel.Get<T>() );
module.Bind<L>().ToMethod( n => n.Kernel.Get<T>() );
}
}
@ Ian Davis et al. Проблема в том, что:
class Problem
{
[Fact]
static void x()
{
var kernel = new StandardKernel( new ServiceModule() );
var v1 = kernel.Get<IService1>();
var v2 = kernel.Get<IService2>();
var service = kernel.Get<ConcreteService>();
Console.WriteLine( service.CallCount ); // 3
Assert.AreEqual( 1, service.CallCount ); // FAILS
}
}
Потому что каждая активация (за Bind
) каждый раз инициализируется.
РЕДАКТИРОВАТЬ 2: То же самое, когда вы используете следующую более урезанную версию:
static class Helpers
{
public static void Singleton<K, L, T>( this NinjectModule module )
where T : K, L
{
module.Bind<T>().ToSelf().InSingletonScope();
module.Bind<K>().ToMethod( n => n.Kernel.Get<T>() );
module.Bind<L>().ToMethod( n => n.Kernel.Get<T>() );
}
}