问题
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?
回答1:
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).
回答2:
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.
回答3:
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 (); }
}
回答4:
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.
回答5:
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
回答6:
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.
来源:https://stackoverflow.com/questions/543116/adding-plugin-support-interface-or-base-class-to-inherit