Communication & Data sharing

Topics: Prism v4 - WPF 4
Oct 20, 2011 at 7:25 PM

Hi,

I have read very carefully the prism MSDN documentation on "Communicating Between Loosely Coupled Components" but I want to be sure that I understood correctly when & how to use the event aggregator and the shared service.

I hope that you can help me checking my understanding. I am taking a simple example for that purpose:

I suppose that I want to develop an application that is able to load a list of records and expose several subsets (eventually overlapping) of the loaded data in various views (interacting differently with the user). Once the loading is done, if the user select a record in a view, the other views are notified in order to react if they are also containing the record.

To my mind, it can be done with:

- a shared service which manage the data loding

- three GUI modules respecting the MVVM pattern

The shared service exposes an interface in the infrastructure library which defines an event DataLoaded(List<Record> data).

As it is a shared service, the view model class of the GUI modules can use dependency injection in order to access it ([ImportingConstructor]) and have the possibility to subscribe to this event. When they receive the event, they can populate the associated models (ObservableCollection?) with a subset of the data (depending on some criterion).

Besides that, there is a class (defined in the Infrastructure library) RecordSelected : CompositePresentationEvent<Record>. The three view module can have access to the shared service EventAggregator through dependency injection and subscribe this event. They are also publishing it when there is a click on a record. In this case, the other modules receive it and can react accordingly by checking if they contain the record too.

I hope my example is clear enough so you can help me...

Does this structure seems ok to you? Can you provide me some corrections/advice if not?

Thanks a lot,

Best,

Developer
Oct 21, 2011 at 12:35 PM

Hi,

From the description of this structure, the approach you're following seems like a valid possibility to achieve your scenario:

For loading the data asynchronously, it looks reasonable to have a shared service, which also defines an event for when the data has been loaded completely. In this case using the event aggregator would be a bit of an overkill, since you're already sharing this service, thus allowing communication between decoupled components, none of which need to know the implementation of the service.

Then, for notifying that a record has been selected, using the event aggregator seems to be a good choice in my opinion, since you're only transmitting an event ("This item has been selected").

I hope you find this helpful.

Guido Leandro Maliandi 
http://blogs.southworks.net/gmaliandi

Oct 23, 2011 at 3:03 PM
Edited Oct 23, 2011 at 3:03 PM

Hi Guido,

 

Thanks a lot for your quick answer (and sorry for my late reply :)). Your explanations confirm my thoughts.

I take advantage of your kindness and ask you complementary questions:

- In the case that I want to handle multiple selection, It seems to me that I can create a selection manager as a shared service or group the selection manager into the data loading shared service. What is your opinion on this?

- Another question concerns the identification of records. For you, is it better to identify the records with an id property (and introduce an id manager as a shared service) or only consider the reference for comparison? This is a more general question but if you can help me on this too, I will be grateful :)

Thanks a lot,

Best,

Developer
Oct 24, 2011 at 1:32 PM
Edited Oct 24, 2011 at 2:02 PM

Hi,

Both of the decisions you're mentioining here will depend on your personal preference and project requirements. On the other hand, here are some recommendations based on my understanding of your scenario:

I believe that, for your first concern, it would be better to divide the functionality of managing selection of items and retrieving data, especially if you might some day modify the implementation of your data access service. This would on instance imply separating the responsibilities of your classes.

As for your second one, I believe having an Id property is a good idea, since you can also use it later to serialize the object and store it in a database, for example. You could also override the Equals method of your entities to check whether they're the same instance by checking only the Id property.

I hope you find this helpful.

Guido Leandro Maliandi 
http://blogs.southworks.net/gmaliandi

Oct 25, 2011 at 6:46 AM

Thanks again for your answer!
It helps me a lot choosing the right solution. I totally agree with you regarding the ID. But the associated issue is the attribution of new ID. To my mind, in this case I should also introduce a shared service that is managing the IDs. Maybe delegate the record creation in this shared service in order to affect the ID at the same time. What's your opinion on this?
Thanks again,
Best,
Thibaut

Developer
Oct 25, 2011 at 8:50 PM

Hi,

Based on my understanding, using a shared service (akin to a factory) to manage the attribution of the Ids seems to be a valid approach, this way you will keep separating the responsibilities of your classes, but as Guido mentioned above, remember that having an Id property is in my opinion useful if you are planning to serialize your data and store it in a database, xml or similar.

Thanks,

Agustin Adami
http://blogs.southworks.net/aadami


Oct 26, 2011 at 4:10 PM

Hi,

Thanks for your answer. I am likely to use serialization so I will definitely use this.

I will abuse of your kindness and ask you other questions. Just tell me when you're tired of my questions :).

- coming back to the dataloader shared service, if I want to handle several several loading in parallel. I was thinking of creating this service as a factory that provides DataLoaderThread. Is it the right way to do it?

- I have another different concern regarding the logger shared service. Prism is providing a ILoggerInterface so that you can use your own implementation. I want to use NLog and take advantage of its filtering capabilities (you can get the currentClassLogger and in the configuration file use a rule to filter on namespace). I am facing difficulties to integrate it into prism because the logger is a singleton so the principle of getting the current class loggers does not seem obvious to set up. Have someone used NLog before with prism? Or do you have an idea how I can do it?

Thanks again,
Best

Le 25 oct. 2011 22:50, "aadami" <notifications@codeplex.com> a écrit :
Developer
Oct 26, 2011 at 4:53 PM

Hi,

For your first question, using a background thread to handle several loading operations in paralell makes sense. You might find this article useful, where the WPF threading model is explained:

Threading Model

Also, in case you find some difficulties regarding specifically to WPF's threading model, you might find better support in the WPF forum, as it is not strictly related to Prism's guidance.

As for your second one, I haven't tried NLog with Prism. Yet, based on my understanding of what you've mentioned, it seems that, in order to integrate the custom NLog mechanism with Prism's ILoggerFacade, it would be better to rely on NLog's custom features (since they exceed the Log method exposed in the ILoggerFacade interface), and create a custom implementation of the ILoggerFacade interface that calls the NLog basic logging methods. That is to say, you could use NLog for your general purpose logging needs (using the current class logger and such features), and on the other hand make the Prism logger communicate its events (such as the bootstrapper's events) to NLog.

To this end, you could override the CreateLogger method in your bootstrapper to provide this implementation of the ILoggerFacade interface.

I hope you find this helpful.

Guido Leandro Maliandi 
http://blogs.southworks.net/gmaliandi

Oct 26, 2011 at 5:18 PM
Hi Guido,
Thanks for your quick answer.
For the threading stuff, thanks for the link. I will have a deep look soon.
As for NLog, I am not sure I am inderstanding correctly your explanation:
You suggestion consists in:
- For prism general purpose, wrapping NLog into a custom implementation of ILoggerFacade
- For specific class purpose:
* Using NLog directly by adding a reference to NLog in the modules and calling the getCurrentClassLogger
OR
* Extending the wrapper and use the shared service to access the currentClassLogger?
Sorry for asking further explanation,
Best

2011/10/26 GuidoMaliandi <notifications@codeplex.com>

From: GuidoMaliandi

Hi,

For your first question, using a background thread to handle several loading operations in paralell makes sense. You might find this article useful, where the WPF threading model is explained:

Threading Model

Also, in case you find some difficulties regarding specifically to WPF's threading model, you might find better support in the WPF forum, as it is not strictly related to Prism's guidance.

As for your second one, I haven't tried NLog with Prism. Yet, based on my understanding of what you've mentioned, it seems that, in order to integrate the custom NLog mechanism with Prism's ILoggerFacade, it would be better to rely on NLog's custom features (since they exceed the Log method exposed in the ILoggerFacade interface), and create a custom implementation of the ILoggerFacade interface that calls the NLog basic logging methods. That is to say, you could use NLog for your general purpose logging needs (using the current class logger and such features), and on the other hand make the Prism logger communicate its events (such as the bootstrapper's events) to NLog.

To this end, you could override the CreateLogger method in your bootstrapper to provide this implementation of the ILoggerFacade interface.

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Read the full discussion online.

To add a post to this discussion, reply to this email (CompositeWPF@discussions.codeplex.com)

To start a new discussion for this project, email CompositeWPF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on CodePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at CodePlex.com


Developer
Oct 26, 2011 at 5:49 PM
Edited Oct 26, 2011 at 5:49 PM

Hi,

In my previous suggestion I recommended you to use NLog directly, not to extend the wrapper and use the shared service to access the current class logger. This seems to be the most easy approach to follow, since it doesn't imply the necessity of a deep knowledge of NLog, nor it needs you to extend the ILoggerFacade interface. All this, while allowing to centralize your logging features in NLog, by "forwarding" Prism's logs to it.

I hope you find this helpful.

Guido Leandro Maliandi 
http://blogs.southworks.net/gmaliandi

Oct 26, 2011 at 5:57 PM

Ok. That what I was thinking. Thanks again. I will certainly come back to you soon:)

Le 26 oct. 2011 19:49, "GuidoMaliandi" <notifications@codeplex.com> a écrit :

From: GuidoMaliandi

Hi,

In my previous suggestion I recommended you to use NLog directly, not to extend the wrapper and use the shared service to access the current class logger. This seems to be the most easy approach to follow, since it doesn't imply the necessity of a deep knowledge of NLog, nor it needs you to extend the ILoggerFacade interface.

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Read the full discussion online.

To add a post to this discussion, reply to this email (CompositeWPF@discussions.codeplex.com)

To start a new discussion for this project, email CompositeWPF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on CodePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at CodePlex.com