Adding Plugin Support : Interface or Base class to inherit?
Asked Answered
C

6

3

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?

Ceto answered 12/2, 2009 at 20:36 Comment(0)
P
5

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).

Paperboard answered 12/2, 2009 at 21:13 Comment(5)
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 :)Ceto
I think this is a good start : codeplex.com/MEF/Wiki/… - I'll look into it more, thanks for the answer.Ceto
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 :) )Ceto
@Slough: Glad you were able to get everything working. Yes, MEF makes adding plugin support to an application so much easier.Paperboard
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 monoaddins.codeplex.com).Mythological
P
4

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.

Phore answered 12/2, 2009 at 20:40 Comment(1)
Wow, limitation of multiple inheritance is a good point that I never thought, cheers for that.Ceto
S
4

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 (); }
}
Seringa answered 12/2, 2009 at 20:48 Comment(4)
Why would you add the extra complexity/overhead of this PluginBase class? Seems very useless to me, and error-prone.Jarrell
@Jarrell originally I was thinking such a think so I can simpy provide some extra standard function with that base class.Ceto
Ah, okay, I understand now. The example here doesn't do a good job of showing that, though.Jarrell
No, this example is horrible in that it doesn't show any default functionality at all, sorry.Seringa
G
2

There is a good post on this topic here: Plugin API design

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

Giule answered 12/2, 2009 at 20:39 Comment(1)
@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.Genitor
O
1

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

Oldie answered 12/2, 2009 at 20:40 Comment(3)
Is there any advantage of this over interface or inheritance ? Because this sounds a bit less straight forward than implementing an interface to me.Ceto
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.Oldie
+1 for the plugin register callback - cha-ching - I've already developed a class that allows for asynchronous delegate registration.Genitor
P
1

Something that everyone is forgetting to mention is backwards compatibility. You can add new methods to a base class without breaking existing clients while you cannot modify existing interfaces without affecting them.

There are alternatives to avoid compatibility issues with interfaces. For example, you could create an new interface that inherits from the old one when you include new extensions for your application. But this has the drawback of bloating your architecture with types such as IClientInterfaceV2 and IClientInterfaceV3.

My personal suggestion would be to go with an approach like the one suggested by scwagner and create both a base class and an interface. And include a warning to the interface users stating that future versions might break their implementation and that the base class inheritance strategy is the recommended one to avoid future compatibility issues.

Priestcraft answered 21/9, 2011 at 16:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.