During the ramp up for my current enterprise GIS development project I created a few simple VB.NET sample
projects which illustrate some architectural practices I want the team to use.
The first one I’m going to share covers the creation of a plugin framework,
and the use of the Supervising Controller pattern to expose user interface logic
to unit tests. In order to keep the focus on the pattern, and not on the complexities
of what the code is doing, this sample does not use any ArcObjects.
It’s just a very simple example of how you could create “property page”
type functionality that can be extended via plugins.
What is a Plugin-Framework and why would I want one?
Using a plugin framework is a way to design an application so that other
functionality can be added at a later time without needing to modify the
original source code. Putting this in ArcGIS terms, this is similar to adding commands into
ArcMap via it’s plugin framework.
If you are building large complex
applications, supporting a plugin model essentially enables the system to be
extended in a very managed way. Thinking back to ArcGIS – by simply implementing ICommand, you
can add alot of functionality into their application, and ESRI does not have to give you the source code, nor do you need to manage a very complex C++ build process.
Supervising Controller Pattern
Just a quick warning – we’re diving into formal object oriented design patterns here. Previously known as Model View
Presenter, this is a common object oriented design pattern. Martin Fowler (who invented/named it) has
officially
retired the “Model View Presenter” pattern, and created two new ones – Supervising
Controller and Passive View.
You can read up on the details of these patterns by following those links, but
the quick and dirty explanation is that they focus on extracting logic from an
User Interface (windows or web form) into “controller” classes. (A little
pattern nugget to impress your friends with: Autonomous
View is the official name for the “put all the code in the form”
pattern) These controllers handle most of the User Interface logic – and
since they are regular old classes – they are much easier to write unit tests
for.
One of the prime reasons to use Supervising Controller is for
testability. Assuming the view is hard to test, by moving any complex logic into
the controller, we put the logic in a place that’s easier to test. – Martin
Fowler
At first blush this seems like more work – and it actually is more coding.
BUT - if you write tests for the controllers (not covered in the sample), it will make your code more
robust and manageable over the long term.
The Plugin Framework
The plugin part is pretty straight forward. We define an interface for the
plugin, and implement it in the classes which we are going to plug-into the
application.

This is exactly the same as implemeting ICommand. The difference is that
instead of registering a COM class with the windows registry, we add the plugin
by editing the host application’s config file…
<propertypageplugins>
<propertypageplugin name=“Editor“ type=“Research.EditorPluginView, Research.ExamplePlugin“ />
<propertypageplugin name=“Some Different Plugin“ type=“Research.EditorPluginView, Research.ExamplePlugin“ />
</propertypageplugins>
In order to load the plugins into the application we create a configuration
section handler – which I’ve posted
about
in the
past. For more details, I’d suggest checking out this MSDN
article by Roy Osherove. I’d also suggest looking at the code, since there are some other interesting bits in there that I’m skipping over to keep this somewhat short.
The Host Application
The plugins must plug-into something – thus the host application. This is
simply a windows form that will list the registered plugins, and then show the
selected plugin interface on the right side of the form. The image below shows it running.
The Plugins & Supervising Controller
The plugins are located in the “ExamplePlugin” assembly. In fact there is only
one plugin – “EditorPlugin ” – I just register it twice. The pluing itself is a super simple text editor. As I metioned earlier, the plugins themselves
implement the Supervising Controller pattern. Typically this is used with
“forms”, but in order to be pluggable, we are working with user controls. And to be fun, I’m using using inherited user controls.

Inheriting the user control forces a common look and feel -
granted in this case, it’s very simple (just the group box), but in our real app,
it’s got a lot more going on.
To keep things clear, I have setup a standard naming convention – the UI (user control in this
case) is <somename>View, and the Controller is <somename>Controller.
The interface that forms the contract between the two is I<somename>View. Looking at the class model above, we can also see that the View implements IPropertyPluginView – which means that it’s the thing that actually plugs into the application.
So in this case we have:
- EditorPluginView
- EditorPluginController
- IEditorPluginView
Since the Controller must manage the UI, one way to setup a contract between
the two is using an Interface. The interface is implemented by the View, and
consumed by the Controller. The interface simply specifies the methods that the
Controller can call on the View (UpdateText and GetText in this case) and the
events that the View raises and that the Controller can handle (ContentChanged
and Store).
Run Time
When the form is initialized (IPropertyPluginView.Initialize()), it creates it’s controller class and passes in a reference to itself as an IEditorPlugin. The Controller then sinks the Events on the interface, reads the file from disk (if it exists) and updates the text on the form. When the user edits the text the IEditorPluginView.ContentChanged event is raised in the form, and the Controller is notified. When the user clicks the store button, the IEditorPluginView.Store event is raised and the Controller gets the content via IEditorPluginView.GetText, and it stores it away.
Even this simple example could be extended, but this is enough to show how it all works.
Conclusion
While this was a whirlwind of terms and concepts, I encourage you to download the code, and play with it. It’s actually quite easy to implement once you get the hang of it, and it can help make your applications much more testable. I find it much easier to look at real code than to just read the generic explanations of patterns, so I hope this helps if you are thinking about implemeting a plugin framework or Supervising Controller in .NET
Download the code
Other Reading:
The Polymorphic Podcast has a series of great screen casts and
audio clips that go over the details of the Model View patterns. I highly
recommend these specifically, and the podcast in general.
MSDN Article: Creating a Plugin
Framework. This is from 2003, and deals with ASP.NET but the concepts have
not changed.