I'm using Ninject Event Broker extensions and I have two services. ServiceOne is the Publisher of an event. ServiceTwo is the subscriber. ServiceOne doesn't have a hard dependency to ServiceTwo, I'm creating the dependency using the DependencyCreation extension.

Here are the requirements:

  • I want to define a one-to-one event between these two objects. Only the ServiceTwo instance created by DependencyCreation should receive the event.
  • If there are other instances of ServiceTwo further down in the object graph they shouldn't receive the event. (this shouldn't be the case but I want to account for it)
  • ServiceTwo should be disposed of when ServiceOne is disposed.
  • This is a web application and the life of ServiceOne should only be for one request.

Basically I'm just trying to recreate the behaviour of me writing:

var publisher = new Publisher();
var subscriber = new Subscriber();
var subscriber2 = new Subscriber();
publisher.MyEvent += subscriber.MyEventHandler;

One publisher. One subscriber. Subscriber2 doesn't get the event.

Here's my code:

this.Bind<IServiceOne, ServiceOne>().To<ServiceOne>().Named("ServiceOne").OwnsEventBroker("ServiceOne").RegisterOnEventBroker("ServiceOne");
this.Kernel.DefineDependency<IServiceOne, IServiceTwo>();
this.Bind<IServiceTwo>().To<ServiceTwo>().WhenParentNamed("ServiceOne").InDependencyCreatorScope().RegisterOnEventBroker("ServiceOne");

Two questions.

Does this fulfill my requirements? Is there a better way?

有帮助吗?

解决方案

I don't normally like to answer my own question but seeing as this has been quiet for a while, I've been testing my code sample and it appears to work fine. To clean up the creation of these dependencies and the whole event broker registration process I created some extension methods. First off an IsPublisher extension that creates a scoped event broker:

    public static ISubscriberBuildingSyntax IsPublisher<TPublisher>(this IBindingWhenInNamedWithOrOnSyntax<TPublisher> syntax)
    {
        string name = Guid.NewGuid().ToString();
        syntax.Named(name);
        syntax.OwnsEventBroker(name).RegisterOnEventBroker(name);
        return new SubscriberBuildingSyntax<TPublisher>(syntax, name);
    }

Secondly, a generic CreateSubscriberDependency method that creates a dependency using Dependency Creator:

    public ISubscriberBuildingSyntax CreateSubscriberDependency<TSubscriber>() where TSubscriber : class
    {
        this.syntax.Kernel.DefineDependency<TPublisher, TSubscriber>();
        this.syntax.Kernel.Bind<TSubscriber>().ToSelf().WhenParentNamed(this.name).InDependencyCreatorScope().RegisterOnEventBroker(this.name);
        return this;
    }

I can then call this like so:

     this.Bind<IRegistrationService>().To<RegistrationService>()
            .IsPublisher()
            .CreateSubscriberDependency<RoleService>();

This creates an Event Broker scoped to the RegistrationService instance with a RoleService dependency that is tied to the life of RegistrationService.

I can then register RegistrationService with InRequestScope to limit this to the life of one request.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top