Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement properly plugins in C#?

Tags:

c#

plugins

I'm trying to add plugins to my game and what I'm trying to implement is this:

  • Plugins will be either mine or 3rd party's so I would like a solution where crashing of the plugin would not mean crashing of the main application.

  • Methods of plugins are called very often (for example because of drawing of game objects).

What I've found so far:

  • 1) http://www.codeproject.com/KB/cs/pluginsincsharp.aspx - simple concept that seems like it should work nicely. Since plugins are used in my game for every round I would suffice to add the Restart() method and if a plugin is no longer needed Unload() method + GC should take care of that.

  • 2) http://mef.codeplex.com/Wikipage - Managed Extensibility Framework - my program should work on .NET 3.5 and I don't want to add any other framework separately I want to write my plugin system myself. Therefore this solution is out of question.

  • 3) Microsoft provides: http://msdn.microsoft.com/en-us/library/system.addin.aspx but according to a few articles I've read it is very complex.

  • 4) Different AppDomains for plugins. According to Marc Gravell ( Usage of AppDomain in C# ) different AppDomains allow isolation. Unloading of plugins would be easy. What would the performance load be? I need to call methods of plugins very often (to draw objects for example).

    • Using Application Domains - http://msdn.microsoft.com/en-us/library/yb506139.aspx

    • A few tutorials on java2s.com

Could you please comment on my findings? New approaches are also welcomed! Thanks!

like image 535
Martin Vseticka Avatar asked Apr 15 '10 09:04

Martin Vseticka


2 Answers

You can define a public interface which the plugin's must implement. Then with the use of reflection you can scan a "plugin" folder for any classes implementing that interface, then create an instance of that class.

From you're code just work on the interface and call the needed method's. About crashing, always make sure that calls to the "plugin" interface are always encapsulated in a try/catch block. If an exception occurs you can always dispose the plugin

like image 89
Jasper Avatar answered Sep 30 '22 13:09

Jasper


I suspect your two requirements of:

  1. fast performance with drawing objects and
  2. a plugin crash would not crash your app

are going to conflict.

To really ensure a buggy plugin doesn't crash your app, you have to load it in a separate AppDomain (as you've identified already). But you're going to take a performance hit, as the whole point of AppDomains is they isolate instances of objects. So you're, at minimum, going to have to serialize arguments to your plugins (possibly using MarshalByRef objects or Remoting). And I suspect that will mean serializing a good chunk of your game state (which sounds like it at least consists of some sort of image). On the plus side, AppDomains live in the same process space, so the overhead isn't as bad as cross-process communication.

Unloading plugins is as simple as unloading the AppDomain.

Because you have to serialise arguments, you can do validation of your game state after the plugin processes it.

I did some toying with AppDomains once. It takes a few seconds to construct one, in my experience. That may affect how many plugins you load into each AppDomain.

like image 44
ligos Avatar answered Sep 30 '22 14:09

ligos