Jump to content

an unpractical primer into .NET, Reflection and building your own plugins

- - - - -

  • Please log in to reply
1 reply to this topic

#1
sam_coder

sam_coder

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 372 posts
Hey Guys,
I took the time today, to write a sample application I think some of you beginner, intermediate types might enjoy playing with. It's not really intended to be "best practice", it's literally an experiment, for fun.

[ATTACH]3954[/ATTACH]

I call the application "Plugin Example". It's made up of a few C# Projects,
  • ExtendableApp - A Windows Forms Application, Demonstrating the experiment
  • PluginFramework - A class library, containing the common interfaces and reflection logic
  • FlatfileWriterPlugin - A class library, containing a "Plugin" that writes to a text file
  • EventWriterPlugin - A class library, containing a "Plugin" that writes to the windows event log

Now, a word of caution. This is just an experiment, and this type of solution in a production environment would have some heavy potential problems. While it isn't that uncommon to load external assemblies in this manner, you have to realize that loading them in the current AppDomain, will mean you cannot unload them without restarting the application. But I wanted to keep the experiment simple enough for most of you to grasp.

Secondly, Reflection is known to be both really powerful, and notably heavy. Use it with care.

Lastly, the plugins may require you to run the IDE in Administrator mode, since one writes to the event viewer, and the other by default writes to a file in the root of C:.

Moving on. Visual Studio 2008 professional was used in building this experiment. It would upgrade just fine into a newer edition of visual studio. I'm not 100% certain about the express editions. However you could also open this just fine in sharp develop, a particularly fantastic alternative and open source IDE.

Lets have some fun!

If you take a look at the PluginFramework project, you will notice a few files. Let's first look at IOutputPlugin.cs.

This is an interface. You can think of an interface as a contract. It doesn't implement anything, it just provides a "view" of an object if you will. In this case, a class that implements this interface, must implement an Output Method, as described.

Secondly, I have a custom OutputPluginAttribute, which allows me to apply custom metadata to my source code. The definition on this, is stating that to a class, I can apply the attribute, with a name property. We will use this Name property, to identify the plugins we create.

Lastly, we have PluginManager.cs. For you beginners, this might look a little intimidating. But basically we have a method that scans a set of directories for "dll files", attempts to load them as assemblies, and enumerates types from within those assemblies that have the OutputPlugin Attribute applied to them.

Upon locating any plugins, it will attempt to create an instance of that plugin, and stick it in a hash table, keyed by the name. So that we could use a plugin like this:


PluginManager.MLoadedOutputPlugins["plugin name"].Output("some data");


make sense? Well, stay with me.

Let's look at ExtendableApp. This is the application. This application references the PluginFramework to obtain the plugin functionality. If you open Program.cs, you will see that we have a very simple pattern. Load Plugins, create the MainForm, and kick off the main application loop.

The MainForm itself, is laid out pretty simply. Attaching a screenshot.
Attached File  mainform_designer.png   15.77K   36 downloads

The idea is that in the input, you will be able to enter some arbitrary data. This data will be sent to whatever plugin is selected.

Plugins that have been loaded, will show up on the right side of the form. As you would expect, these plugins are selectable. The highlighted plugin will be the one used.

The 'Submit' button will cause the data in the input box, to be pushed through the loaded plugin.

The messages box, just shows redundant information, pertaining to things that are going on. It adds to the coolness, come on!

I stuck a few goodies in there, again, not really intended to be practical, but just to show you some of the potential with C#. Experiments are always funner when you play.

One such goodie, is the fact that the messages box will format text based on the width of the form (yes you can resize it), and it will attempt to wrap text in a way that keeps it clean and easy to read.

The other two projects, are plugin implementations. And this is where the effort of having built the PluginFramework, and using reflection to load them pays off. If you were to run this, it will automatically detect the two plugins. If you closed the applcation, and went into the bin directory where it is built, you could delete one of the plugins, and then double click on the ExtendableApp.exe, and you will notice that plugin no longer shows up. So these really are loaded at runtime.

Don't delete the PluginFramework, it's required by the application, and both plugins.

If you look at the FlatfileWriterPlugin\FlatfileWriter.cs file, you can see the entire implementation of the plugin. It's pretty simple.

It must implement the IOutputPlugin interface to work. And you must add the OutputPlugin Attribute to the Class. This makes it detectable.

Of course once you implement the interface, you must also implement everything described in the Interface. And in this case, it's the Output(string data) method.

Anyways, run the app, play with it, and review the code. If you have any questions at all, I'll do my best to answer it.

Happy Coding!

Attached Files



#2
sam_coder

sam_coder

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 372 posts
I was looking at the source I posted. Originally I was planning on providing a secondary mechanism for detecting the plugins, using IsAssignableFrom to detect classes that implemented the said interface. It proved to be much less reliable, and so I didn't include it. Unfortunately, I also forgot to remove some of the comments from PluginManager. So if you see anything referring to that, sorry, my bad.... =)




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users