views:

1800

answers:

7

I'd like to provide some way of creating dynamically lodable plugins in my software. Typicial way to do this is using the LoadLibrary WinAPI fuction to load a dll and calling GetProcAddress to get an pointer to a function inside that dll.

My question is how do I dynamically load a plugin in C#/.Net application?

A: 

Are you in control of the creation of new plugins? If so then I would imagine you create a base class with some common function definitions like New() or DoWork() and wave some polymorphism jazz-hands, and there you have it!

*May not work as advertised.

Mark Glorie
+11  A: 

The following code snippet (C#) constructs an instance of any concrete classes derived from Base found in class libraries (*.dll) in the application path and stores them in a list.

using System.IO;
using System.Reflection;

List<Base> objects = new List<Base>();
DirectoryInfo dir = new DirectoryInfo(Application.StartupPath);

foreach (FileInfo file in dir.GetFiles("*.dll"))
{
    Assembly assembly = Assembly.LoadFrom(file.FullName);
    foreach (Type type in assembly.GetTypes())
    {
        if (type.IsSubclassOf(typeof(Base)) && type.IsAbstract == false)
        {
            Base b = type.InvokeMember(null,
                                       BindingFlags.CreateInstance,
                                       null, null, null) as Base;
            objects.Add(b);
        }
    }
}

Edit: The classes referred to by Matt are probably a better option in .NET 3.5.

Zooba
+3  A: 

Basically you can do it in two ways.

The first is to import kernel32.dll and use LoadLibrary and GetProcAddress as you used it before:

[DllImport("kernel32.dll")]

internal static extern IntPtr LoadLibrary(String dllname);

[DllImport("kernel32.dll")]

internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);

The second is to do it in the .NET-way: by using reflection. Check System.Reflection namespace and the following methods:

First you load the assembly by it's path, then get the type (class) from it by it's name, then get the method of the class by it's name again and finally call the method with the relevant parameters.

Biri
+17  A: 

As of .NET 3.5 there's a formalized, baked-in way to create and load plugins from a .NET application. It's all in the System.AddIn namespace. For more information you can check out this article on MSDN: Add-ins and Extensibility

Matt Hamilton
+3  A: 

One tip is to load all plugins and such into an own AppDomain, since the code running can be potentially malicious. An own AppDomain can also be used to "filter" assemblies and types that you don't want to load.

AppDomain domain = AppDomain.CreateDomain("tempDomain");

And to load an assembly into the application domain:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
Assembly assembly = domain.Load(assemblyName);

To unload the application domain:

AppDomain.Unload(domain);
Patrik
+2  A: 

The article is a bit older, but still applicable for creating an extensibility layer within your application:

Let Users Add Functionality to Your .NET Applications with Macros and Plug-Ins

Purple Ant
+2  A: 

Yes, ++ to Matt and System.AddIn (a two-part MSDN magazine article about System.AddIn are available here and here). Another technology you might want to look at to get an idea where the .NET Framework might be going in the future is the Managed Extensibility Framework currently available in CTP form on Codeplex.

jolson