How to resolve a presenter using framework

Topics: Prism v2 - Silverlight 2, Prism v2 - WPF 3.5
Jun 10, 2009 at 10:34 AM
Edited Jun 10, 2009 at 10:39 AM

The situation is: I have an abstract  PresenterBase class with abstract method

public abstract class PresenterBase{

abstract Guid ID();

void ExecuteCommand(string commandName);

}

And some of presenters a derived from PresenterBase. When a presenter do something it sends some information + ID. Something happens and called object returns result + caller ID using an event. A controller catch this event and should recognize a presenter using ID from the event. So I'm trying to do the next code:

     var asm = System.Reflection.Assembly.GetExecutingAssembly();

            foreach (Type tp in asm.GetTypes())

            {

                if (tp.IsInterface)

                {

                    PresenterBase presenter = null;

                    presenter = _container.Resolve<tp>() as PresenterBase;

                    if ((presenter != null) && (presenter.ID() == command.CallerID))

                    {

                        presenter.ExecuteCommand(command.Command);

                    }

                }

            }

But have a problem in the line presenter = _container.Resolve<tp>() as PresenterBase;

Is there an another way to pass through an each presenter and check the condition for ID(). There is another reason whi this approach is't good - if presenter was't  created before but just registered .Resolve<> invoke a contructor and memory is fillings an presenter that maybe never be called during this session.

 

 

Jun 11, 2009 at 7:11 PM

Hi dunenko,

 

To fix the problem with the line of code you mentioned you might use the following one:

 

presenter = unityContainer.Resolve(tp) as PresenterBase;

 

Though I don't know you whole scenario, but there might be some drawbacks in the approach you are using:

1.       The use of reflection might have performance issues. More over if the method is going to execute each time an event is published.

2.       You will need to register all the types in the container. If not an exception is going to be thrown when trying to resolve an unregistered type.

3.       Even if you register all the types you need, you are creating a new instance of the presenter (and calling the ExecuteCommand method on the new instance, not in the one that actually published the event). (This might not be an issue if you intend it to be that way)

 

If I understood your scenario correctly, you need the presenter to send some information (using an event?) that will trigger some operation. When the operation is finished, you need to execute the ExecuteCommand method on the presenter.

To achieve this you might, instead of handling the event published when the operation is finished in the controller,  have it handled in the presenters using a filters (to filter by the presenter's ID). For example:

 

event.Subscribe(ExecuteCommand, ThreadOption.PublisherThread, false, command => command.CallerID == this.ID);

 

This way you will avoid all of the above drawbacks, reduce the controller's logic, and keep everything decoupled (though having the ID going around might not be that decoupled).

  

Hope it helps!

 

Matias Bonaventura

http://blogs.southworks.net/matiasb

Jun 15, 2009 at 5:49 AM

Hi, Matias!

You understood my scenario exactly. I'm registering presenters with ContainerControlledLifetimeManager inside a RegisterType method, so I don't care about the third drawback. but at the same time you are right the Resolve method will create a new instance of the presenter if it wasn't resolved before. I'm really wanted to decrease of code lines processing the back event at the one place of code, because another team persons will be create presenters and with this approach they should't care about handlig the event. I estimated the pros and cons and now  using your way.

Thank you for your justification advice. It's really helped.