0

In Microsoft's view injection sample/article they have the code like the following:

public void Initialize()
{
    this.RegisterViewsAndServices();
    EmployeesPresenter presenter = this.container.Resolve<EmployeesPresenter>();
    IRegion mainRegion = this.regionManager.Regions[RegionNames.MainRegion];
    mainRegion.Add(presenter.View);
}

http://msdn.microsoft.com/en-us/library/dd458920.aspx

here Presenter is resolved which contains the public property of type IEmployeesView and thats used for injecting the view to the region. The benefit of resolving the presenter is that it gets automatically tied to the view (by taking it in constructor (via unity)). However don't you think the Presenter is prone to garbage collection because nothing has reference to presenter after the scope of initialize method ends?

View/ViewModel obviously won't have reference to presenter unless VM/View has an event which is subscribed by presenter. We can go into an inconsistent state in which the view is active but the presenter is garbage collected.

To prevent garbage collection of presenter probably we'll need a KeepAlive property in ViewModel that just holds the reference to presenter for preventing its GC but that sounds hacky to me. What do you do or would do in this situation?

Please note that in a situation where there will be multiple instances of the view, registering the presenter with ContainerControlledLifetimeManager is not feasible. Also if the mode of communication for presenter (with view) is via commands and the commands happen to be DelegateCommands of prism then they will only keep weak reference to the presenter so that won't serve the purpose either.

Muhammad Hasan Khan
  • 34,648
  • 16
  • 88
  • 131
  • Doesn't *the container* hold the reference to the Presenter, that being the reason you use it? The code shown is just grabbing a reference to that Presenter, and sticking its View into a region... – Dan J Dec 09 '10 at 21:10
  • What are you referring to as a container? – Muhammad Hasan Khan Dec 09 '10 at 21:42
  • Container is the UnityContainer. Typically a Resolve<> itself won't add the object to the container unless you register the type as a ContainerControlledLifetimeManager or a PerInstanceLifetimeManager (which you can write) which will add it to the container. – aqwert Dec 09 '10 at 22:32
  • Interestingly if nothing references the Presenter and the view does not expose events then the only way I can see the Presenter doing anything will be internally there is a timer which sets data on the view otherwise nothing can call the presenter to perform any operations. – aqwert Dec 09 '10 at 22:37
  • There can be multiple instances of the view. Container controlled life time manager doesn't make sense there. And the way to ocommunicate with the view is via commands and DelegateCommands in prism keep a weak reference to the subscriber. – Muhammad Hasan Khan Dec 10 '10 at 04:06

1 Answers1

2

This is a complicated question about lifetime. In this example in the Prism documentation, the implementation of the EmployeesPresenter hooks up to an event on the EmployeesListPresenter:

public EmployeesPresenter(
            IEmployeesView view,
            IEmployeesListPresenter listPresenter,
            IEmployeesController employeeController)
        {
            this.View = view;
            this.listPresenter = listPresenter;
            this.listPresenter.EmployeeSelected += new EventHandler<DataEventArgs<BusinessEntities.Employee>>(this.OnEmployeeSelected);
            this.employeeController = employeeController;

            View.SetHeader(listPresenter.View);
        }

This ties the lifetime of the EmployeesPresenter to the lifetime of the IEmployeesListPresenter. It is registered with the container like this:

this.container.RegisterType<IEmployeesListPresenter, EmployeesListPresenter>();

Not staticly or ContainerControlledLifetime, either. Now we have to look at the implementation of EmployeesListPresenter. Here is its constructor:

public EmployeesListPresenter(IEmployeesListView view,
            IEmployeeService employeeService)
        {
            this.View = view;
            this.View.EmployeeSelected += delegate(object sender, DataEventArgs<BusinessEntities.Employee> e)
            {
                EmployeeSelected(sender, e);
            };
            view.Model = employeeService.RetrieveEmployees();
        }

Now we see that the EmployeesListPresenter is tied up in the lifetime of the IEmployeesListView.

So, the lifetime of the EmployeesPresenter is the same as the EmployeesListView, which will be essentially as long as it is in the control tree.

This is a pretty confusing sample. You will find that the Prism 4 samples are much more straightforward... I would recommend looking at them and possibly upgrading to Prism 4 if you have a choice.

Anderson Imes
  • 25,500
  • 4
  • 67
  • 82
  • Thats true that life time is implicitly handled in some situation because presenter has hooked up on some event published by view but this is not something that can be consistently followed as a pattern in an application. The real question is what life time management strategy does everyone use in a situation like this? – Muhammad Hasan Khan Dec 13 '10 at 17:42
  • 1
    @Hasan Khan: In my case, I don't use MVP... I think it complicates matters too much. I use MVVM and allow the ViewModels to communicate directly by way of the EventAggregator or some other mechanism. I don't think bringing in a third party adds much besides complication. I think you will see this shift in the Prism 4 samples as well. – Anderson Imes Dec 13 '10 at 18:19
  • @Anderson Imes - If you get a chance, please take a look at my question here. http://stackoverflow.com/questions/15049256/wpf-prism-4-1-garbage-collection-memory-issues I also use MVVM but cannot figure out what I have a memory leak in my very simple Prism demo app. – Chris Klepeis Feb 24 '13 at 19:28