views:

331

answers:

5

I'm adding plugin support to my .NET application. A base class sounds reasonable to me, so people can inherit it and override certain calls as well can keep the default functionality or can use some internal helper functions.

Why would I choose interface instead of a base plugin class to inherit? Could you tell which design I should choose and why?

+2  A: 

There is a good post on this topic here: http://stackoverflow.com/questions/351498/plugin-api-design

I would personally use an interface, and let the plugins implement all the details.

Jon Tackabury
@Jon Tackabury: we are still teetering on whether interface, abstract, or attribute; however, the plugins (read the end-users) will have to implement all the details.
dboarman
+4  A: 

Use an interface for the plugin contract. If a certain type of plugin likely shares certain functionality, make an abstract base class that implements the interface. Also ensure that your contracts are in an assembly outside of your actual application.

Keep in mind that in .NET, you don't have multiple inheritance. Requiring implementers to give up their inheritance slot to provide a little functionality for them is not a good idea.

ermau
Wow, limitation of multiple inheritance is a good point that I never thought, cheers for that.
dr. evil
+1  A: 

I think the obvious thing you should do is to let the plugin register callback (delegates) for the individual events it wants to handle. This is the way most frameworks work in .net

In other words, neither base classes nor interfaces. The advantage of this solution is that your plugin does not have to conform to any given external interface or base class, it simply registers for the functionality it needs.

As an example, the "Events" sections in any given asp.net control does it this way: Have a look at UserControl

krosenvold
Is there any advantage of this over interface or inheritance ? Because this sounds a bit less straight forward than implementing an interface to me.
dr. evil
I edited slightly. I may not be getting entirely across here, but what I'm talking about is the *standard* way of doing this thing in .net.
krosenvold
+1 for the plugin register callback - *cha-ching* - I've already developed a class that allows for asynchronous delegate registration.
dboarman
+3  A: 

Why does it have to be one or the other?

You can define the contract that the plugins must follow as an interface which is being referenced everywhere.

Plus, you can also define a base class which implements that interface, but merely has abstract methods that get called for some of the interface functions that you can't provide a default implementation for.

public interface IPlugin
{
    void Initialize ();
    void Stuff ();
}

public class PluginBase : IPlugin
{
    protected abstract DoInitialize ();
    protected abstract DoStuff ();

    void IPlugin.Initialize { this.DoInitialize (); }
    void IPlugin.Stuff { this.DoStuff (); }
}
scwagner
Why would you add the extra complexity/overhead of this PluginBase class? Seems very useless to me, and error-prone.
strager
@strager originally I was thinking such a think so I can simpy provide some extra standard function with that base class.
dr. evil
Ah, okay, I understand now. The example here doesn't do a good job of showing that, though.
strager
No, this example is horrible in that it doesn't show any default functionality at all, sorry.
scwagner
+4  A: 

You should consider taking a look at the System.Addin (MAF) namespace or the Managed Extensibility Framework (MEF). MEF would be the preferred choice even though it is still pre-release as it is much simpler than MAF. Either one of those choices simplify a lot of the plumbing work you will need to do in order to get add-ins loaded and interact with them.

As far as making a choice between an interface and an abstract class, if you go with MAF or MEF some of that will be made for you. The most basic differences in this context are that by providing an abstract base class you provide an inheritance point for custom plugins (written either by you or other developers) and ensure that certain methods/properties provide default behavior and force the derived classes to implement certain required methods/properties. The drawback is that you are limited to a single base class.

Interfaces get around the single base class limitation and still provide an inhertiance point for custom plugins and ensure that certain methods/properties are implemented but can't provide any type of default behavior. You also cannot specify anything other than public members in an interface while an abstract class can have abstract or virtual non-public members (typically protected).

Scott Dorman
This sounds interesting do you know any good article to start it up quickly? Because right now when I look at it, it just looks awfully complex :)
dr. evil
dr. evil
I've just implemented this and it's so much easier than I thought (beside of some stupid mistakes I've done in the first try :) )
dr. evil
@Slough: Glad you were able to get everything working. Yes, MEF makes adding plugin support to an application so much easier.
Scott Dorman
Another option is Mono.Addins. It is a good alternative if you need more advanced add-in handling features, such as add-in dependencies and metadata (see http://monoaddins.codeplex.com).
Lluis Sanchez