[ACCEPTED]-Best way to set up a modular program in C#-module

Accepted answer
Score: 37

I've used stuff like this on projects before, but 39 it's been a while. There are probably frameworks 38 out there that do this kind of stuff for 37 you.

To write your own plug-in architecture, basically 36 you want to define an interface for all 35 the modules to implement, and put this in 34 an assembly shared by both your program 33 and the modules:

public interface IModule
{
     //functions/properties/events of a module
} 

Then your implementors will 32 code their modules to this assembly, preferably 31 with a default constructor.

public class SomeModule : IModule {} ///stuff 

In your program 30 (supposing your modules will be compiled 29 into their own assemblies) you load a reference 28 an assembly containing a module, find the 27 types that implement the module interface, and 26 instantiate them:

var moduleAssembly = System.Reflection.Assembly.LoadFrom("assembly file");
var moduleTypes = moduleAssembly.GetTypes().Where(t => 
   t.GetInterfaces().Contains(typeof(IModule)));

var modules = moduleTypes.Select( type =>
            {   
               return  (IModule) Activator.CreateInstance(type);
            });

If you want to compile 25 the code on the fly: you create a compiler 24 object, tell it what assemblies to reference 23 (System and the one that contains IModule, plus 22 any other references needed), tell it to 21 compile the source file into an assembly. From 20 that, you get the exported types, filter 19 keeping those which implement the IModule, and 18 instantiate them.

//I made up an IModule in namespace IMod, with string property S
string dynamicCS = @"using System; namespace DYN 
             { public class Mod : IMod.IModule { public string S 
                 { get { return \"Im a module\"; } } } }";

var compiler = new Microsoft.CSharp.CSharpCodeProvider().CreateCompiler();
var options = new System.CodeDom.Compiler.CompilerParameters(
       new string[]{"System.dll", "IMod.dll"});

var dynamicAssembly= compiler.CompileAssemblyFromSource(options, dynamicCS);
//you need to check it for errors here

var dynamicModuleTypes = dynamicAssembly.CompiledAssembly.GetExportedTypes()
    .Where(t => t.GetInterfaces().Contains(typeof(IMod.IModule)));
var dynamicModules = dynModType.Select(t => (IMod.IModule)Activator.CreateInstance(t));

Look up tutorials on plug-in 17 architectures and loading dynamic assmeblies 16 to get a better feel for doing this kind 15 of stuff. This is just the start. Once 14 you get the basics down, you can start doing 13 some really cool things.

As for handling 12 the metadata (module X is named YYY and 11 should handle events A,B and C): Try to 10 work this into your type system. You could 9 make up different interfaces for the different 8 functions/events, or you could put all the 7 functions on one interface, and put attributes 6 (you'd declare these in the shared assembly) on 5 the module classes, using the attributes 4 to declare which events the module should 3 subscribe to. Basically you want to make 2 it as simple as possible for people to write 1 modules for your system.

 enum ModuleTypes { ChannelMessage, AnotherEvent, .... }

 [Shared.Handles(ModuleTypes.ChannelMessage)]
 [Shared.Handles(ModuleTypes.AnotherEvent)]
 class SomeModule : IModule { ... }

or

 //this is a finer-grained way of doing it
 class ChannelMessageLogger : IChannelMessage {}
 class PrivateMessageAutoReply : IPrivateMessage {} 

have fun!

Score: 18

The Managed Extensibility Framework (MEF) provides exactly what you are looking 7 for except they call it a Plugin architecture. You 6 could provide a common interface which you 5 users could build on and then MEF could 4 scan a directory for dlls and load any Exports 3 dynamically.

For example your plugin authors 2 could create something like

[Export(typeof(IModule))]
public class MyModule : IModule
{
   void HandleMessage(ChannelEventArgs e) {}
}

Then your code 1 could look something like this:

void OnChannelMessage(ChannelEventArgs e)
{
  foreach(IModule module in Modules)
  {
     module.HandleMessage(e);
  }
}

[Import]
public IEnumerable<IModule> Modules { get; set; }
Score: 4

Please have a look a microsoft's Managed 3 Extensibility Framework (MEF) - It proposes 2 to do some of what you want, and provides 1 a lot of other features:

Google results for 'managed extensibility framework'

Score: 3

There is another option in the hearth of 3 .NET 3.5 called Managed AddIn Framework 2 (MAF). Check the following links out.

Sample 1 and Tools: http://clraddins.codeplex.com/

MAF Blog: http://blogs.msdn.com/clraddins/

A good article: http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/08/13/Build-AddIns-with-System-AddIn.aspx

Score: 2

MEF - Managed Extensibility Framework is 4 the buzzword right now - I think that would 3 be the best fit.

If that doesnt do the trick 2 you could also look up on Prism, they have another 1 approach to implement modules.

More Related questions