Ninject создает единичный экземпляр несколько раз в доменном событии
Доменная служба
public void MyDomainService {
void DoSomething() {
Raise<MyDomainEvent>(new DomainEvent());
}
}
Служба приложений Singleton
public void SingletonApplicationService {
// Handles MyDomainEvent
private int _myRandomId = new RandomId();
public SingletonApplicationService() {
_logger.Info("Hello, I'm " + _myRandomId + ". I got resolved.");
}
public void Handle(DomainEvent event) {
_logger.Info("Hello, I'm " + _myRandomId + ". I received a domain event.");
}
}
Привязки ядра
Kernel.Bind<IDomainService>().To<DomainService>()
.InRequestScope();
Kernel.Bind<ISingletonApplicationService>()
.To<SingletonApplicationService>()
.InSingletonScope();
Kernel.Bind<IDomainEventHandler<MyDomainEvent>>()
.To<SingletonApplicationService>();
// tried as singleton and per request
Запуск приложения
Kernel.Get<ISingletonApplicationService>();
var domainService = Kernel.Get<IDomainService>();
domainService.DoSomething();
Это производит следующий журнал:
"Hello, I'm 421. I got resolved."
// domain event occurs here
"Hello, I'm 455. I got resolved."
"Hello, I'm 421. I received a domain event.");
"Hello, I'm 455. I received a domain event."); // and I crash because of that!
1 ответ
Поскольку вы используете Ninject, вам также необходимо зарегистрировать IDomainEventHandler<MyDomainEvent>
иметь одноэлементную область, так как область по умолчанию является временной.
Kernel.Bind<IDomainEventHandler<MyDomainEvent>>()
.To<SingletonApplicationService>()
.InSingletonScope();
Однако я полагаю, что у вас будет один экземпляр для каждой службы, то есть один экземпляр для ISingletonApplicationService
и единственный экземпляр для IDomainEventHandler<MyDomainEvent>
, Вы можете хотеть разрешить оба к одному и тому же экземпляру. Одним из способов достижения этого и иметь ленивый экземпляр будет
Kernel.Bind<SingletonApplicationService>().ToSelf().InSingletonScope();
Kernel.Bind<ISingletonApplicationService >().ToMethod(
c => c.Kernel.Get<SingletonApplicationService>());
Kernel.Bind<IDomainEventHandler<MyDomainEvent>>().ToMethod(
c => c.Kernel.Get<SingletonApplicationService>());