Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load assemblies located in a folder in .NET Core console app

I'm making a console app on the .NET Core platform and was wondering, how does one load assemblies (.dll files) and instantiate classes using C# dynamic features? It seems so much different than .NET 4.X and it's not really documented...

For example, let's say I have a class library (.NET Core) and it has only one class:

namespace MyClassLib.SampleClasses {     public class Sample     {         public string SayHello(string name)         {             return $"Hello {name}";         }          public DateTime SayDateTime()         {             return DateTime.Now;         }     } } 

So the name of the dll file would be MyClassLib.dll and it's located in /dlls/MyClassLib.dll.

Now I want to load this in a simple console app (.NET Core) and instantiate the Sample class and call the methods using dynamic features of C# in the following console app:

namespace AssemblyLoadingDynamic {     public class Program     {         public static void Main(string[] args)         {             // load the assembly and use the classes         }     } } 

Note: By .NET Core, I mean the RC2 version.

like image 337
Vahid Amiri Avatar asked Jun 18 '16 09:06

Vahid Amiri


2 Answers

Currently running against netcoreapp1.0 you don't actually need to go to the extent of implementing your own AssemblyLoader. There is a Default that exists which works just fine. (Hence @VSG24 mentioning that the Load doesn't do anything).

using System; using System.Runtime.Loader;  namespace AssemblyLoadingDynamic {     public class Program     {         public static void Main(string[] args)         {             var myAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(@"C:\MyDirectory\bin\Custom.Thing.dll");             var myType = myAssembly.GetType("Custom.Thing.SampleClass");             var myInstance = Activator.CreateInstance(myType);         }     }    } 

with project.json looking like:

{   "version": "1.0.0-*",   "buildOptions": {     "emitEntryPoint": true   },    "dependencies": {     "Microsoft.NETCore.App": {       "type": "platform",       "version": "1.0.1"     },     "System.Runtime.Loader": "4.0.0"   },    "frameworks": {     "netcoreapp1.0": {       "imports": "dnxcore50"     }   } } 
like image 117
Rob Avatar answered Oct 06 '22 13:10

Rob


Not sure if it's the best way to do it but here's what I came up with:

(Only tested on .Net Core RC2 - Windows)

using System; using System.Linq; using System.Reflection; using System.Runtime.Loader; using Microsoft.Extensions.DependencyModel;  namespace AssemblyLoadingDynamic {     public class Program     {         public static void Main(string[] args)         {             var asl = new AssemblyLoader();             var asm = asl.LoadFromAssemblyPath(@"C:\Location\Of\" + "SampleClassLib.dll");              var type = asm.GetType("MyClassLib.SampleClasses.Sample");             dynamic obj = Activator.CreateInstance(type);             Console.WriteLine(obj.SayHello("John Doe"));         }          public class AssemblyLoader : AssemblyLoadContext         {             // Not exactly sure about this             protected override Assembly Load(AssemblyName assemblyName)             {                 var deps = DependencyContext.Default;                 var res = deps.CompileLibraries.Where(d => d.Name.Contains(assemblyName.Name)).ToList();                 var assembly = Assembly.Load(new AssemblyName(res.First().Name));                 return assembly;             }         }     } } 

MyClassLib.SampleClasses is the namespace and Sample is the type aka class name.

When executed, it will try to load the SampleClassLib.dll compiled class library in the memory and gives my console app access to MyClassLib.SampleClasses.Sample (take a look at the question) then my app calls the method SayHello() and passes "John Doe" as name to it, Therefore the program prints:

"Hello John Doe"

Quick note: The override for the method Load doesn't matter so you might as well just replace its content with throw new NotImplementedException() and it shouldn't affect anything we care about.

like image 31
Vahid Amiri Avatar answered Oct 06 '22 13:10

Vahid Amiri