Adding Plugin Support : Interface or Base class to inherit?

南笙酒味 提交于 2019-12-06 03:56:23

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

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.

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 (); }
}
Jon Tackabury

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.

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

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!