The nuts I mentioned in my last article have been cracked. Instead of having to resort to reflection and other complexity, the solution turns out to be simple and elegant usage of object orientation. It involved a lot of thinking.
The idea I was carrying around was to implement a generic abstraction layer around the IPlugin interface. Instead of having to implement the Execute() function over and over in your own classes, I just wanted to implement the events I need.
This results in a much cleaner and simpler implementation. Not having to worry about the plumbing, speeds up development and makes you more productive as well!
A tale of two base classes
The solution turns out to be a tale of two base classes:
TestPlugin (implementation) derives from:
PluginBase (base class) derives from:
PluginFoundation (base class) implements:
PluginBase is the abstract base class that you use to implement your own class (TestPlugin).
In your own class, you override the methods you need from the base class. If you omit to implement your overridden function, you end up with a NotImplementedException.
PluginFoundation is the abstract base class of the PluginBase. In Plugin Foundation the function signatures are implemented as abstract functions. In the execute method (which is implemented for IPlugin) the appropriate abstract function is called. As the function in the PluginFoundation is abstract, the overridden function in the derived class (PluginBase) is called.
In your own class (which has as a parent the PluginBase) you override the function you need. This results in the execution of your function.
Simple, elegant and effective.
But why the two bases classes?
I hear you wonder, why implementing two base classes, can’t we just use PluginFoundation?
Sure that’s possible, however as I implemented all functions in the PluginFoundation class as abstract functions, the compiler demands an implementation for the abstract functions.
This would lead to a large number of empty functions in your implementation. The second base class (PluginBase) handles this overhead for you, enabling you to implement the functions you need by overriding the base implementation.
Cool… where are the goodies?
For your convience, I put up a zip file containing the implementation. The code is posted under the MIT license.