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>());
Другие вопросы по тегам