Limiting exposure to host application

Sep 25, 2010 at 5:39 AM

I am looking for advice on how to limit the required knowledge to get an extension to work with a host. 

I have a Silverlight application which has a Toolbar.  The toolbar contains various controls.  Each control is a MEF import.  It is possible that some of them may be provided by the users themselves (similar to adding a button to Visual Studio toolbars).

To give further details on my specific question, I have a button on the toolbar that is a toggle button.  When the user clicks it, interacting with the main application is slightly different.  To be even more specific, imagine that the application is something like Expression Design and the button in question is the Pan (hand icon) button.  Click it, and the cursor changes to a hand when over the artboard and pressing the moust button lets you drag it around.  This is the basic functionality I want.

If the button was hardcoded into the toolbar (not a MEF plugin) this would be easy.  Being a plugin doesn't make it too difficult either, however, it seems that the artboard and the rest of the application would need to have intimate knowledge of the plugins existence.  I need to try and avoid this the best I can.  I don't want to hard code things in to the application everytime someone wants to add a new button.  I am looking for advice on the best way to approach this.

Sep 26, 2010 at 3:59 PM
Edited Sep 26, 2010 at 4:02 PM

A lot of this can be learned and further explained by the composite application samples, the Prism stuff. Provided by the patterns and practices group at Microsoft.

Though I'd like to point out that unless you create your own message passing system that abstracts the interactions of controls you'll not be able to hide the dependency on Silverlight. With that in mind you'd want decide from the beginning if a Silverlight dependency is okay. You can still make progress with things like MVVM but ultimately your plug-in infrastructure will have to be built with Silverlight (WPF) in mind. 

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

Sep 26, 2010 at 7:51 PM

If I am understanding you correctly you want the shell to notify the buttons that something interesting happened, without the shell being coupled to the buttons, is that correct?

 

Sep 27, 2010 at 4:52 AM

I assume by "shell" you are referring to the application that is hosting the MEF extensions.  In that case, the answer to your question is yes but there is a little more to it then that.  Not only do some of the toolbar items need to know when things happen to the main application but they also need to perform actions on some of the components in the main application or influence some of those actions in some way.  In my example, clicking on part of the application and dragging will either pan the screen (like in expression design) or select items on the screen.  Which one occurrs depends on which button on the toolbar is pressed.  Both toolbar buttons are MEF extensions.  At the moment, I have hardcoded the knowledge of these buttons in to my main application so it can determine which operation to perform.  I would like to abstract this.

The more I think of it the more I imagine that I am going to need some sort of abstraction layer or contract.  The main application will need to expose events and certain properties via this contract that extensions can manipulate.  As far as my panning/selection modes would go, I could see defning a Mode property as a core property in the application and exposing accessing to it to extensions.  I haven't done this before so I wasn't sure the best way to approach this.

Todd

Sep 27, 2010 at 5:46 AM

There are several approaches you could use here.

One you could use a pub/sub mechanism to fire "events" between components in a loosely coupled fashion. Prism's EventAggregator or Laurent Bugnion's Messenger class in MVVM light are two solutions that come to mind. In these cases the contract is the event. For example let's say you had a pluggable Order Management app. An OrderSelected event could be fired which the parts can subscribe to. When you use this type of approach you need to put the eventing mechanism into the catalog thus allowing which ever part wants to access to import it. Using this approach you can go either direction from the shell to the parts, or from the parts to the shell. The advantage of this approach is it works well for when you have 1 to many consumers that need to respond to different occurances in the app.

A second approach which would be more relevant for cases where the parts themselves need to manipulate the shell would be to provide a set of specific contracts which those parts import. For example you can export an IMenuService which is shared in the container. Whenever parts need to manipulate the menu they import it.

A third approach if you are in SL or WPF is to export ICommands which the UI binds to. This would specifically be for cases where you want to plug in UI handlers directly.,

Whichever approach you use depends on the scenarios, but in practice a hybrid may be the best choice.

 

Sep 27, 2010 at 5:24 PM

I am using MVVM Light and was thinking about the Messenger class but I hadn't yet looked into it closely.  I will definately focus on it a bit and see how I can use it for my needs.  I also like your thoughts/suggestions on importing ICommands and having a contract in place, that can be imported, for working on the shell.  It seems like my best option smight be, as you mentioned, to combine all of your suggestions.

I know where to go to read up on the Messenger and EventAggregator.  Can you direct me to any specific sources for more information on your other two suggestions?

Thanks,

Todd

Sep 27, 2010 at 5:34 PM

This article in the Prism docs covers the approaches. You can also see my Prism article (shameless plug) in the section on "Modules and Services". 

Using MEF you would not need to manually register as the services would just go in the catalog. RegionManger in Prism is an example of one such service.

Cheers

Glenn

 

 

 

Sep 27, 2010 at 6:39 PM

Thank you very much Glenn.  I started looking in to Prism last night.  I was initially worried about going this route because I heard that Prism is rather larger and some developers complained about this.  It seems to me that I can pick and choose what portions of Prism that I use.  I am using MEF and MVVM Light so I would be willing to move forward with Prism if those will work with Prism.  I wasn't possitive that Prism provided all the things that you were suggesting but I started thinking that it probably did and your most recent reply seems to confirm this.  I will continue looking in to it and read your article.

Thanks again for your input.

Todd

Sep 27, 2010 at 7:53 PM

Sure Todd. You can definitely pull the bits of Prism you want as needed, as that was part of the specific design. Regardless of whether you use it's bits or nots, the guidance / docs provide good references for addressing your solution.

Cheers

Glenn

Oct 2, 2010 at 8:38 AM
Edited Oct 2, 2010 at 8:39 AM

I myself learned all I know from composition by studing Prism. I've even ported major parts of Prism to work in ASP.NET WebForms. This is just to say that what Glenn says is absolutely true, it was a lot of work, but I did learn a lot in the process and it shows just how Prism can be adapted other frameworks/scenarios, not just Silverlight/WPF.