# [.net] How do you make plugins in C#

## Recommended Posts

GameMasterXL    100
I am trying to make plugins in C# that are MDI windows so i have my main program shell and then my plugins are in there own little windows and i want to load them windows has MDI windows how do i make a plugin system like this? i searched google for this and found nothing i only found one tutorial that i am using but it is only using controls and not forms.

##### Share on other sites
ernow    732
A form is *very* similar to a control. It is just a class.

An easy way is to define a (base) proxy class (or factory) that should be implemented by a plugin module. This class should allow e.g. the querying for supported features and the construction of the plugin features.

Cheers

##### Share on other sites
Rob Loach    1504
The first thing you have to find out is what you plan on making each plugin do. Each one has to have a familiar interface. Let's say you're making plugins that have one method named "DoStuff". This method would do different stuff depending on what plugin is loaded. So, let's make the plugin interface:

public interface IPlugin{    void DoStuff();}

As you can see, we have a simple interface here named IPlugin that has a method named "DoStuff". You'd put this in your main assembly. Now when you're making and compiling plugins, you'd have each plugin implement the IPlugin interface. Then you know whether it's a correctly made plugin if it implements the DoStuff method from IPlugin. Here's a sample of a plugin that implements the main IPlugin:
public class SomePlugin : IPlugin{    public void DoStuff()    {        System.Console.WriteLine("My name is SomePlugin and I'm doing stuff!");    }}

I hope you understand what I'm getting at. If you need a demonstration, feel free to download and check out GakScript. There are J#, JScript, and Boo language plugins made for it that use a similar method to what I was talking about.

[Edited by - Rob Loach on December 4, 2009 12:30:27 PM]

##### Share on other sites
Guest Anonymous Poster
Sorry this is GameMasterXL i just can't remember my pass on this account lol. Thanks for code but i am a tad bit confused this is the tutorial i am learning off http://www.codeproject.com/csharp/PluginsInCSharp.asp and i can not seem to change the control into a mdi window :(. It just exceptions out saying a type error occured how can i sort this? so i can load my plugin forms has MDI windows in my main application. Hope you can help thanks in advance.

##### Share on other sites
GameMasterXL    100
Quote:
 Original post by ernowA form is *very* similar to a control. It is just a class.An easy way is to define a (base) proxy class (or factory) that should be implemented by a plugin module. This class should allow e.g. the querying for supported features and the construction of the plugin features.Cheers

I tried it but it says the types are out :(. I do not know what is wrong it just exceptions out and i do not know if i can debug my application without it giving me an error saying it can't load .dlls.

##### Share on other sites
Quote:
 Original post by GameMasterXLI am trying to make plugins in C# that are MDI windows so i have my main program shell and then my plugins are in there own little windows and i want to load them windows has MDI windows how do i make a plugin system like this?

I'm writing a program at work that does just this. The approach I decided to take is a little different than how ernow and Rob described.

When I started working on my shell, one of the requirements was to integrate some legacy .NET applications into it as plugins. After examining the source, I found that all of the applications were SWForms and were run in Main with Application.Run(new ...). (This is the reason the nasty looking cast in my source is always legit.) I decided to go with a plugin attribute and use it to name and describe the program I was "assimilating." This approach made it very easy to make each of the applications a plugin without changing any existing code, and only having to add two lines (a using statement and the plugin attribute, both in the main form class).

I have written a quick, albeit somewhat nasty and inefficient, example solution, which you can download here. Please note that not much work has been put into this example, and you would want to add error checking, a plugin manager, etc., if you decided to use this approach. I hope it does help, though. Note that the code was created in VS 2005, but you could revert it without much trouble (I don't use generics or any of the other new language features).

All that said, this approach is kind of a cheap fix. If I got to start over (we're six months into development now O.o), I would most likely create an abstract class and inherit from it. This also presents a solution to only one type of plugin: Forms. This will not work with console applications (it would probably break the program, but I've never tried it). It also leads to some pretty nasty-looking casts in your shell... However, it works. *shrug*

Oh, and resize the OGL plugin to see the spinning (and inside-out!) triangle and cube. I haven't worked with Tao in awhile, and it shows!

Anyway, HTH!

##### Share on other sites
GameMasterXL    100
Thanks for code but i am slighty confused.

##### Share on other sites
Alright, here's a quick explanation:

First, I created the PluginLibrary, which only contains the PluginAttribute class, but could contain other plugin-related classes as well (such as common controls, interfaces, etc.). The attribute is pretty simple, it just required you to add [Plugin("MyPluginName")] on your main form class (don't forget to add PluginLibrary.dll as a reference!).

Next, I created the shell. The only code you're really interested in lies in Form1.cs. Note that I am "using PluginLibrary" on line 11. The constructor simply calls InitializeComponent() to set up the form; the only interesting note is that this.IsMdiContainer = true; is in InitializeComponent.

Next, the OnFormLoad method is called, which goes through the Plugins folder and searches for *.dll files. For each of these files, I create a Type array (via reflection) and see if any of those types have my plugin attribute (type.GetCustomAttributes(typeof(PluginAttribute), false)). If any of the types do have this attribute, then I create a new menu item, add PluginAttribute.PluginName as the menu text and set up a common OnClick event (Plugin_Click).

The Plugin_Click method is much the same. I go through each plugin, grab the types, and check for my attribute (hey, I said this example is inefficient! ...make a manager or something that can contain all of this informtaion, and you'll not have use reflection in this method. Reflection is expensive!). Here's where it gets a little different: I compare the clicked menu item's text to the PluginAttribute.PluginName. If they match, then I call Activator.CreateInstance(type), cast it as a Form (<--- that nasty cast I was talking about), set its MdiParent to the shell, and finally show the form. (With a manager, you can also have multiple plugins with the same name...this example will always call the first one.)

The two plugin projects were simply to show how easy it is to make a .NET Windows app a plugin in MyShell, and how starkly different those plugins could be. If you add a Main to each project and add Application.Run(new ...) to the Main and set each project as a Windows app, you'll see that each of them will compile and run on their own.

I hope this helps, but if not, let me know; I'll try to explain it a bit differently. I can also write a manager and make this code a bit more efficient if it would help.

##### Share on other sites
GameMasterXL    100
Yes that would help alot thanks.

##### Share on other sites
Sorry it took me so long to get back to you. I have now written a PluginManager and added it to the solution. I have also modified the shell to use the PluginManager instead of handling all the plugins on its own.

I have to be honest, the PluginManager code is somewhat scary, partly because of my sloppy code. I've tried to comment it as best as I could without being excessive.

Let me know if it helps, or if you have any additional problems.

Oh, and there are a few more features you may want to implement, such as importing plugins into your plugin directory. This should be pretty easy, and you would actually get to use the Invalidated event. [smile]

Finally, don't exit the shell without first closing the NeHe plugin. I think that the way I implemented the OnPaint function in that plugin causes it to lock up. I should have used a timer instead. Try closing it with the Adder open, though!

Again, HTH.

##### Share on other sites
Guest Anonymous Poster
Here are some links that I found to be useful (some more than others) when developing my plugin framework. I apologize that I can't share mine, though, because it belongs to my employer.

Also, as a new visitor to these forums, I do not know how to linkify these urls, sorry.

http://www.cuj.com/documents/s=8209/cujweb0301walcheske/

http://blogs.msdn.com/junfeng/archive/2004/02/09/69919.aspx

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp05162002.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/factopattern.asp

http://www.mattberther.com/2004/10/000559.html

http://www.csharpfriends.com/quickstart/howto/doc/Remoting/nutshell.aspx

http://www.codeproject.com/dotnet/PluginManagerClassBrk.asp

http://www.thecodeproject.com/csharp/extensibleui.asp

http://www.codeproject.com/csharp/DynamicPluginManager.asp

http://blogs.msdn.com/jasonz/archive/2004/05/31/145105.aspx