views:

259

answers:

5

I'm trying to implement a plug-in like application. I know there are already several solution out there but this is just going to be proof of the concept, nothing more. The idea would be to make the application main application almost featureless by default and then let the plugins know about each other, having them have implement all the needed features.

A couple of issues arise:

  1. I want the plugins at runtime to know about each other through my application. That wouldn't mean that at code-time they couldn't reference other plugin's assemblies so they could use its interfaces, only that plugin-feature initialization should be always through my main app. For example: if I have both plugins X and Y loaded and Y wants to use X's features, it should "register" its interest though my application to use its features. I'd have to have a kind of "dictionary" in my application where I store all the loaded plugins. After registering for interest in my application, plugin Y would get a reference to X so it could use it. Is this a good approach?
  2. When coding plugin Y that uses X, I'd need to reference X's assembly, so I can program against its interface. That has the issue of versioning. What if I code my plugin Y against an outdated version of plugin X? Should I always use a "central" place where all assemblies are, having there always the up to date versions of the assemblies?

Are there by chance any books out there that specifically deal with these kinds of designs for .NET?

Thanks

edit: I think people are drifting away from the 2 questions I made. I can take a look at both MEF and #develop, but I'd like to get specifics answers to the questions I made.

+3  A: 

Look into the System.AddIn namespace. It's a little lower-level than MEF, and so should give you the "implement it myself" experience you're looking for.

Joel Coehoorn
+1  A: 

Once I done it using this example. I loved it, but it was couple years ago, I think there might be better solutions now. As long as I remember the basic idea was that there is abstract class in your program, and your plug-ins inherit that class and compiled as DLLs... or something similar using Interfaces. Anyways that approach worked great for me. Later I added a filesystemwatcher so it could load those DLL plugins while it is running.

To load an Assembly

To get the types the assembly exposes

m0s
Just what I was going to say. Added some links to MSDN pages of interest.
Skizz
Yes but that is a kinda simplistic example. Just basic reflection and simple OO design.
devoured elysium
Yeah it is... only reason I suggested is because It is capable of solving the problems you specified above... with effort of course... you would have to write sophisticated plug-in manager. If you are looking for something out of box then just go with MEF like everyone suggested... it seems to be very powerful.
m0s
+2  A: 

There is a good book on building what you are looking for: Dissecting a C# Application: Inside SharpDevelop. Here's a link: http://www.icsharpcode.net/OpenSource/SD/InsideSharpDevelop.aspx

The SharpDevelop application is fully plugin-based and the book talks about how they built it, the pitfalls they faced, and how they overcame it. The book is freely available from the site, or you can buy it too.

Garo Yeriazarian
+4  A: 

I recommend looking into MEF. This is a new way of doing plugins in .NET. It is the recommend way of doing new addins for VS2010, for example. I've not used it myself, but what I've looked into about it looks great. Adding this as an answer on prodding of others :)

Matt Greer
A: 

About the two specific issues you exposed:

1) I'm not sure what are you trying to achieve, but my guess is that you want to have lazy initialization of features, and maybe lazy loading of add-ins. If that's the goal, what you are proposing might work. So it could work like this:

  • The Y plugin provides a list of features it needs to use (it could be done for example through a specific interface implementation or through an xml manifest).
  • The X add-in implements an API which allows initializing a feature, with a method like Initialize(featureId).
  • The host application gets the feature list required by Y, loads/initializes the X plugin, and calls Initialize for each feature.
  • The host application also provides a GetFeature() method which Y can use to get a reference to a 'feature' object, which would be implemented in X.

However, if the plugin Y has direct access to the X API, I think it is unnecessary to have all that infrastructure for registering features. Y can just access the X features by directly using the X API, and Y would take care of lazy initializing each feature when required. For example, Y could just call SomeXFeature.DoSomething(), and the implementation of that class would initialize the feature the first time it is used.

2) If the API of an assembly changes, any assembly depending on it may break. Plugins are just assemblies which depend on other assemblies, so they will also break. Here are some things you can do to alleviate this problem.

  • Assign a version number to each plugin. This could be just the assembly version.
  • When loading a plugin, ensure that all dependencies can be properly satisfied (that is, all plugins on which it depends must be present and have the required version). Refuse to load the plugin if dependencies can't be satisfied.
  • Implement a plugin management tool, to be used for all plugin install/uninstall operations. The manager can check dependencies and report errors when trying to install plugins with unsatisfied dependencies, or when trying to uninstall a plugin on which other plugins depend.

Similar solutions are used by the Mono.Addins framework. In Mono.Addins, each add-in has a version number and a list of add-ins/versions on which it depends. When loading an add-in, the add-in engine ensures that all dependent add-ins with the correct versions are also loaded. It also provides an API and a command line tool for managing the installation of add-ins.

Lluis Sanchez