Vraag Ninject-bindingen voor een dispatcher-implementatie van een interface


Ik heb een interface:

public interface IService
{
    void DoStuff(int parm1, string parm2, Guid gimmeABreakItsAnExampleK);
}

Ik zou graag Ninject (v3) bindingen willen configureren zodat ik een "dispatcher" shuffle-methode naar meerdere instanties van IService, zoals zo:

public sealed class DispatcherService : IService
{
    private IEnumerable<IService> _children;

    public DispatcherService(IEnumerable<IService> children)
    {
        this._children = children.ToList();
    }

    public void DoStuff(int parm1, string parm2, Guid gimmeABreakItsAnExampleK)
    {
        foreach(var child in this._children)
        {
            child.DoStuff(parm1, parm2, gimmeABreakItsAnExampleK);
        }
    }
}

Mijn bindingen, die er zo uitzien, eindigen echter met een uitzondering tijdens runtime, wat wijst op een cyclische afhankelijkheid:

this.Bind<IService>().To<DispatcherService>();

this.Bind<IService>().To<SomeOtherService>()
    .WhenInjectedExactlyInto<DispatcherService>();
this.Bind<IService>().To<YetAnotherService>()
    .WhenInjectedExactlyInto<DispatcherService>();

Is dit mogelijk? Zo ja, wat doe ik verkeerd? Kan de ninja ontsnappen aan deze cyclische afhankelijkheidsdaad?


10
2017-10-11 19:28


oorsprong


antwoorden:


Als uw coördinator het is enkel en alleen IService die een lijst met IServices als een parameter gaat gebruiken, dit werkt (ik heb getest):

kernel.Bind<IService>().To<DispatcherService>().When(x => x.IsUnique);
this.Bind<IService>().To<SomeOtherService>()
    .WhenInjectedExactlyInto<DispatcherService>();
this.Bind<IService>().To<YetAnotherService>()
    .WhenInjectedExactlyInto<DispatcherService>();

De reden dat When clausule werkt voor deze zaak is dat de IsUnique gebied van IRequest wordt ingesteld op true wanneer uw constructor om één exemplaar van een service vraagt. Sinds jouw DispatcherService roept op tot een IEnumerable, de waarde is false bij het activeren van de DispatcherService. Dat voorkomt dat de cirkelafhankelijkheid gebeurt.

Echt, elke correcte manier om de kernel te vertellen niet te proberen de DispatcherService in zichzelf te injecteren zou werken (dit is slechts een potentieel bruikbaar voorbeeld).

Bewerken: de meer expliciete manier om je circulaire afhankelijkheid eenvoudigweg te kortsluiten, lijkt dit te zijn:

kernel.Bind<IService>().To<DispatcherService>().When(
   request => request.Target.Member.DeclaringType != typeof (DispatcherService));

2
2017-10-16 03:36



Ik moet toegeven dat ik niet zo bekend ben met de Ninject API, maar ik denk dat dit de slag zou slaan:

kernel.Bind<IService>().To<DispatcherService>();   

kernel.Bind<IEnumerable<IService>>().ToMethod(() => new IService[]
{
    kernel.Get<SomeOtherService>(),
    kernel.Get<YetAnotherService>(),
});

1
2017-10-11 21:39



Waarom niet af van IService in de DispatcherService en noem het IDispatcherService en zorg ervoor dat de called services (ontvangers) IService implementeren?


1
2017-10-15 15:39



Je zou de twee subsets (ofwel Dispatcher of de ontvangers) uit de weg kunnen ruimen door een van hen een Named Binding te maken en de naam vervolgens gebruiken als een manier om de ene naar de andere te voeden (via een NamedAttribute of in uw bedrading)


0
2017-10-12 09:22