Is this right to inject the container/kernel to the main application presenter? [duplicate]
Asked Answered
H

1

0

I'm using Ninject to handle my dependencies.

My ApplicationPresenter is responsible to dispatch the user calls to features throughout the application, hence the need to inject multiple factories at once, thus the container itself. It handles an MDI GUI.

  1. Is there a better approach?
  2. Is it okay to make it so?

ApplicationPresenter

public class ApplicationPresenter 
    : Presenter<IApplicationView>
    , IApplicationPresenter {
    public ApplicationPresenter(IApplicationView view, IKernel dependencies) 
        : base(view) {
        Dependencies = dependencies;
        View.Connect += OnConnect;
        View.ManageInquiries += OnManageInquiries;
    }

    private static readonly IKernel Dependencies;
}

The ApplicationPresenter is responsible for orchestrating the system's feature in the MDI window such as:

  1. User authentication
  2. Managing inquiries...

I have an AuthenticationPresenter and an InquiryManagementPresenter which shall both be called from the ApplicationPresenter like so:

User clicks on...

public class ApplicationPresenter : ... { 
    // See ctor for event subscription...

    private void OnConnect() {
        AuthenticationPresenter authentication = 
            Dependencies.Get<IAuthenticationPresenter>();
        authentication.ShowView();
    }

    private void OnManageInquiries() {
        InquiriesManagementPresenter inquiriesManagement = 
            Dependencies.Get<IInquiriesManagementPresenter>();
        inquiriesManagement.ShowView();
    }
}

And within the InquiriesManagementPresenter, I have dependencies on other presenters as:

  • NewInquiryPresenter
  • EditInquiryPresenter
  • CancelInquiryPresenter
  • ApproveInquiryPresenter...

Ninject modules

public class ApplicationModule : NinjectModule {
    public void Load() {
        Bind<IApplicationPresenter>().To<ApplicationPresenter>().InSingletonScope();
        Bind<IApplicationView>().To<ApplicationForm>();
    }
}

public class AuthenticationModule : NinjectModule {
    public void Load() {
        Bind<IMembershipService>().To<MembershipService>();
        Bind<IAuthenticationPresenter>().To<AuthenticationPresenter>().InSingletonScope();
        Bind<IAuthenticationView>().To<AuthenticationForm>();
        Bind<ICredentials>().To<Credentials>().InSingletonScope();
        Bind<IUser>().To<User>().InSingletonScope();
        Bind<IDatabaseInstance>().To<DatabaseInstance>().InSingletonScope();
        Bind<IDatabaseUser>().To<DatabaseUser>().InSingletonScope();
    }
}

public class InquiryManagementModule : NinjectModule {
    public void Load() {
        Bind<INewInquiryPresenter>().To<NewInquiryPresenter>().InSingletonScope();
        Bind<INewInquiryView>().To<NewInquiryForm>();
        Bind<IEditInquiryPresenter>().To<EditInquiryPresenter>().InSingletonScope();
        Bind<IEditInquiryView>().To<EditInquiryForm>();
        Bind<IInquiryRepository>().To<InquiryRepository>();
        // ...
    }
}

So, I find it simpler to pass the Ninject's IKernel from from a presenter to another for those that require multiple functionality like the InquiryManagementPresenter or the ApplicationPresenter.

So still, is it this okay or is there another much better way to achieve this?

Hammertoe answered 31/3, 2014 at 4:39 Comment(3)
Though the question in possible duplicate addresses quite the same problem, the context is radically different, as I am not looping through cases, but only working an MDI application. I would agree to rely on the answers provided to the question if at least I could understand how to "translate" it to my context.Hammertoe
@MarkSeemann, thanks for pointing to this question. Beside my searches, I had not find this question. Aside, it only requires for the TestParser to to take two arguments, through the TestParser constructor. Actually, that is already what I do. Although I have read the question and all of its answers, my question remains, what is the better approach? Do I create myself a container which will wrap the Ninject IKernel, or do I pass the IKernel directly, or else?... I'm a bit confused here, honestly. I only need a kick start, please.Hammertoe
I've attempted to respond with a proper answer, then :)Fanlight
F
2

You should never pass the DI Container around, because then you're using it as a Service Locator, which is an anti-pattern.

If your ApplicationPresenter requires an AuthenticationPresenter and an InquiriesManagementPresenter, then inject those dependencies:

public class ApplicationPresenter : Presenter<IApplicationView>, IApplicationPresenter
{
    private readonly static AuthenticationPresenter authenticationPresenter;
    private readonly static InquiriesManagementPresenter inquiriesManagementPresenter;

    public ApplicationPresenter(
        IApplicationView view,
        AuthenticationPresenter authenticationPresenter,
        InquiriesManagementPresenter inquiriesManagementPresenter) 
        : base(view)
    {
        this.authenticationPresenter = authenticationPresenter;
        this.inquiriesManagementPresenter = inquiriesManagementPresenter;
        View.Connect += OnConnect;
        View.ManageInquiries += OnManageInquiries;
    }
}

If those presenters have dependencies of their own, it's totally fine: you just build up the entire graph up front, but the AplicationPresenter doesn't have to see any of the sub-graphs.

Fanlight answered 31/3, 2014 at 10:31 Comment(3)
Thanks Mark, I do appreciate it. To sum it up, this means that I have not to worry about the presenters on which depends the InquiriesManagementPresenter? I mean, this presenter depends on its view, and three to four other presenters, those are, the NewInquiryPresenter, EditInquiryPresenter, DeactivateInquiryPresenter, ApproveRejectInquiryReportsPresenter and CancelInquiryPresenter. I have read about the Façade which seemed suitable for me, I guess, and I dislike the fact of it being a static class, because when you access it, it comes out of nowhere! It is not injected.Hammertoe
+1 (I know you're not waiting for it, and I am grateful for your answer) Aside, I guess the the Façade pattern could prove to be useful for my MDI, for instance, that is, my ApplicationPresenter.Hammertoe
I also thought of a Factory of factories or the something alike, so that I could have my presenter factories along. But it also stinks, because when testing the application, this will make a lot to setup for not that much to test.Hammertoe

© 2022 - 2024 — McMap. All rights reserved.