<p>I'd like to provide some way of creating dynamically loadable plugins in my software.
Typical way to do this is using the <a href="http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx" rel="noreferrer">LoadLibrary</a> WinAPI function to load a dll and calling <a href="http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx" rel="noreferrer">GetProcAddress</a> to get an pointer to a function inside that dll.</p>

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

[{'answer_id': 14282, 'author': 'Zooba', 'author_id': 891, 'author_profile': 'https://Stackoverflow.com/users/891', 'pm_score': 5, 'selected': True, 'text': '<p>The following code snippet (C#) constructs an instance of any concrete classes derived from <code>Base</code> found in class libraries (*.dll) in the application path and stores them in a list.</p>\n\n<pre><code>using System.IO;\nusing System.Reflection;\n\nList&lt;Base&gt; objects = new List&lt;Base&gt;();\nDirectoryInfo dir = new DirectoryInfo(Application.StartupPath);\n\nforeach (FileInfo file in dir.GetFiles("*.dll"))\n{\n    Assembly assembly = Assembly.LoadFrom(file.FullName);\n    foreach (Type type in assembly.GetTypes())\n    {\n        if (type.IsSubclassOf(typeof(Base)) &amp;&amp; type.IsAbstract == false)\n        {\n            Base b = type.InvokeMember(null,\n                                       BindingFlags.CreateInstance,\n                                       null, null, null) as Base;\n            objects.Add(b);\n        }\n    }\n}\n</code></pre>\n\n<p><strong>Edit:</strong> The classes referred to by <a href="https://stackoverflow.com/questions/14278/how-to-load-plugins-in-net#14305">Matt</a> are probably a better option in .NET 3.5.</p>\n'}, {'answer_id': 14286, 'author': 'Biri', 'author_id': 968, 'author_profile': 'https://Stackoverflow.com/users/968', 'pm_score': 2, 'selected': False, 'text': '<p>Basically you can do it in two ways.</p>\n\n<p>The first is to import kernel32.dll and use LoadLibrary and GetProcAddress as you used it before:</p>\n\n<pre><code>[DllImport("kernel32.dll")]\n\ninternal static extern IntPtr LoadLibrary(String dllname);\n\n[DllImport("kernel32.dll")]\n\ninternal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);\n</code></pre>\n\n<p>The second is to do it in the .NET-way: by using reflection. Check System.Reflection namespace and the following methods: </p>\n\n<ul>\n<li><a href="http://msdn.microsoft.com/en-us/library/b61s44e8.aspx" rel="nofollow noreferrer">Assembly.LoadFile</a></li>\n<li><a href="http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettype.aspx" rel="nofollow noreferrer">Assembly.GetType</a></li>\n<li><a href="http://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettypes.aspx" rel="nofollow noreferrer">Assembly.GetTypes</a></li>\n<li><a href="http://msdn.microsoft.com/en-us/library/8zz808e6.aspx" rel="nofollow noreferrer">Type.GetMethod</a></li>\n<li><a href="http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.invoke.aspx" rel="nofollow noreferrer">MethodInfo.Invoke</a></li>\n</ul>\n\n<p>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.</p>\n'}, {'answer_id': 14305, 'author': 'Matt Hamilton', 'author_id': 615, 'author_profile': 'https://Stackoverflow.com/users/615', 'pm_score': 5, 'selected': False, 'text': '<p>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 <a href="http://msdn.microsoft.com/en-us/library/system.addin.aspx" rel="noreferrer">System.AddIn</a> namespace. For more information you can check out this article on MSDN: <a href="http://msdn.microsoft.com/en-us/library/bb384241.aspx" rel="noreferrer">Add-ins and Extensibility</a></p>\n'}, {'answer_id': 14312, 'author': 'Patrik Svensson', 'author_id': 936, 'author_profile': 'https://Stackoverflow.com/users/936', 'pm_score': 3, 'selected': False, 'text': '<p>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.</p>\n\n<pre><code>AppDomain domain = AppDomain.CreateDomain("tempDomain");\n</code></pre>\n\n<p>And to load an assembly into the application domain:</p>\n\n<pre><code>AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath);\nAssembly assembly = domain.Load(assemblyName);\n</code></pre>\n\n<p>To unload the application domain:</p>\n\n<pre><code>AppDomain.Unload(domain);\n</code></pre>\n'}, {'answer_id': 15048, 'author': 'Brian G Swanson', 'author_id': 1795, 'author_profile': 'https://Stackoverflow.com/users/1795', 'pm_score': 2, 'selected': False, 'text': '<p>The article is a bit older, but still applicable for creating an extensibility layer within your application:</p>\n\n<p><a href="http://msdn.microsoft.com/en-us/magazine/cc164072.aspx" rel="nofollow noreferrer">Let Users Add Functionality to Your .NET Applications with Macros and Plug-Ins</a></p>\n'}, {'answer_id': 53011, 'author': 'Jason Olson', 'author_id': 5418, 'author_profile': 'https://Stackoverflow.com/users/5418', 'pm_score': 2, 'selected': False, 'text': '<p>Yes, ++ to Matt and System.AddIn (a two-part MSDN magazine article about System.AddIn are available <a href="http://msdn.microsoft.com/en-us/magazine/cc163476.aspx" rel="nofollow noreferrer">here</a> and <a href="http://msdn.microsoft.com/en-us/magazine/cc163460.aspx" rel="nofollow noreferrer">here</a>). Another technology you might want to look at to get an idea where the .NET Framework might be going in the future is the <a href="http://www.codeplex.com/mef" rel="nofollow noreferrer">Managed Extensibility Framework</a> currently available in CTP form on Codeplex.</p>\n'}, {'answer_id': 14185590, 'author': 'cdiggins', 'author_id': 184528, 'author_profile': 'https://Stackoverflow.com/users/184528', 'pm_score': 3, 'selected': False, 'text': '<h2>Dynamically Loading Plug-ins</h2>\n\n<p>For information on how to dynamically load .NET assemblies see <a href="https://stackoverflow.com/questions/1137781/c-sharp-correct-way-to-load-assembly-find-class-and-call-run-method/14184863#14184863">this question</a> (and <a href="https://stackoverflow.com/a/14184863/184528">my answer</a>). Here is some code for loading creating an <code>AppDomain</code> and loading an assembly into it.</p>\n\n<pre><code>var domain = AppDomain.CreateDomain("NewDomainName");\nvar pathToDll = @"C:\\myDll.dll"; \nvar t = typeof(TypeIWantToLoad);\nvar runnable = domain.CreateInstanceFromAndUnwrap(pathToDll, t.FullName) \n    as IRunnable;\nif (runnable == null) throw new Exception("broke");\nrunnable.Run();\n</code></pre>\n\n<h2>Unloading Plug-ins</h2>\n\n<p>A typical requirement of a plugin framework is to unload the plugins. To unload dynamically loaded assemblies (e.g. plug-ins and add-ins) you have to unload the containing <code>AppDomain</code>. For more information see <a href="http://msdn.microsoft.com/en-us/library/c5b8a8f9.aspx" rel="nofollow noreferrer">this article on MSDN on Unloading AppDomains</a>.</p>\n\n<h2>Using WCF</h2>\n\n<p>There is a <a href="https://stackoverflow.com/questions/5801406/c-sharp-wcf-plugin-design-and-implementation">stack overflow question and answer</a> that describe how to use the Windows Communication Framework (WCF) to create a plug-in framework. </p>\n\n<h2>Existing Plug-in Frameworks</h2>\n\n<p>I know of two plug-in frameworks: </p>\n\n<ul>\n<li><a href="http://www.mono-project.com/Mono.Addins" rel="nofollow noreferrer">Mono.Add-ins</a> - As mentioned in <a href="https://stackoverflow.com/a/9045372/184528">this answer to another question</a>.</li>\n<li><a href="http://msdn.microsoft.com/en-us/library/bb384200.aspx" rel="nofollow noreferrer">Managed Add-in Framework (MAF)</a> - This is the <code>System.AddIn</code> namespace as <a href="https://stackoverflow.com/a/14305/184528">mentioned by Matt in his answer</a>.</li>\n</ul>\n\n<p>Some people talk about the <a href="http://msdn.microsoft.com/en-us/library/dd460648.aspx" rel="nofollow noreferrer">Managed Extensibility Framework (MEF)</a> as a plug-in or add-in framework, which it isn\'t. For more information see <a href="https://stackoverflow.com/questions/835182/choosing-between-mef-and-maf-system-addin">this StackOverflow.com question</a> and <a href="https://stackoverflow.com/questions/124040/is-mef-a-replacement-for-system-addin">this StackOverflow.com question</a>.</p>\n'}, {'answer_id': 59571238, 'author': 'LeonardoX', 'author_id': 1683040, 'author_profile': 'https://Stackoverflow.com/users/1683040', 'pm_score': 0, 'selected': False, 'text': '<p>This is my implementation, Inspired in <a href="https://www.codeproject.com/Tips/546639/How-to-create-an-easy-plugin-system-in-Csharp" rel="nofollow noreferrer">this code</a> avoiding to iterate over all assemblies and all types (or at least filtering with linQ). I just load the library and try to load the class which implemets a common shared interface. Simple and fast :)</p>\n\n<p>Just declare an interface in a separated library and reference it in both, your system and your plugin:</p>\n\n<pre><code>public interface IYourInterface\n{\n    Task YourMethod();\n}\n</code></pre>\n\n<p>In your plugin library, declare a class which implements IYourInterface</p>\n\n<pre><code>public class YourClass: IYourInterface\n{\n    async Task IYourInterface.YourMethod()\n    {\n        //.....\n    }\n}\n</code></pre>\n\n<p>In your system, declare this method</p>\n\n<pre><code>using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing System.Linq;\n\npublic abstract class ReflectionTool&lt;TSource&gt; where TSource : class\n{\n    public static TSource LoadInstanceFromLibrary(string libraryPath)\n    {\n        TSource pluginclass = null;\n        if (!System.IO.File.Exists(libraryPath))\n            throw new Exception($"Library \'{libraryPath}\' not found");\n        else\n        {\n            Assembly.LoadFrom(libraryPath);\n\n            var fileName = System.IO.Path.GetFileName(libraryPath).Replace(".dll", "");\n            var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(c =&gt; c.FullName.StartsWith(fileName));\n            var type = assembly.GetTypes().FirstOrDefault(c =&gt; c.GetInterface(typeof(TSource).FullName) != null);\n\n            try\n            {\n                pluginclass = Activator.CreateInstance(type) as TSource;\n            }\n            catch (Exception ex)\n            {\n                LogError("", ex);\n                throw;\n            }\n        }\n\n        return pluginclass;\n    }\n}\n</code></pre>\n\n<p>And call it like this way:</p>\n\n<pre><code>IYourInterface instance = ReflectionTool&lt;IYourInterface&gt;.LoadInstanceFromLibrary("c:\\pathToYourLibrary.dll");\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/14278', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1534/']