如何加载位于.net核心控制台应用程序中的文件夹中的程序集

我正在.Net Core平台上制作一个控制台应用程序,并且想知道,如何使用C#动态function加载程序集(.dll文件)和实例化类? 它似乎与.Net 4.X有很大的不同,并没有真正记录……

例如,假设我有一个类库(.Net Core),它只有一个类:

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

所以dll文件的名称是MyClassLib.dll ,它位于/dlls/MyClassLib.dll

现在我想在一个简单的控制台应用程序(.Net Core)中加载它并实例化Sample类并使用C#的动态function在以下控制台应用程序中调用方法:

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

注意: .Net Core我指的是RC2版本。

目前针对netcoreapp1.0运行,实际上并不需要实现自己的AssemblyLoader 。 存在一个可以正常工作的Default 。 (因此@ VSG24提到Load没有做任何事情)。

 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); } } } 

project.json看起来像:

 { "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" } } } 

不确定这是否是最佳方式,但这就是我想出的:

仅在.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是名称空间, Sample是类型名称。

执行时,它会尝试在内存中加载SampleClassLib.dll编译的类库,并让我的控制台应用程序访问MyClassLib.SampleClasses.Sample (看看问题),然后我的应用程序调用方法SayHello()并传递“ John Doe“作为它的名字,因此程序打印:

"Hello John Doe"

快速注意:方法Load的覆盖并不重要,所以你也可以用throw new NotImplementedException()替换它的内容,它不应该影响我们关心的任何事情。

谢谢你的分享。 它也与Net Core 1.0一起使用。 如果程序集在同一路径上需要另一个程序集,则可以使用下面的代码示例。

 using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Loader; using Microsoft.Extensions.DependencyModel; public class AssemblyLoader : AssemblyLoadContext { private string folderPath; public AssemblyLoader(string folderPath) { this.folderPath = folderPath; } protected override Assembly Load(AssemblyName assemblyName) { var deps = DependencyContext.Default; var res = deps.CompileLibraries.Where(d => d.Name.Contains(assemblyName.Name)).ToList(); if (res.Count > 0) { return Assembly.Load(new AssemblyName(res.First().Name)); } else { var apiApplicationFileInfo = new FileInfo($"{folderPath}{Path.DirectorySeparatorChar}{assemblyName.Name}.dll"); if (File.Exists(apiApplicationFileInfo.FullName)) { var asl = new AssemblyLoader(apiApplicationFileInfo.DirectoryName); return asl.LoadFromAssemblyPath(apiApplicationFileInfo.FullName); } } return Assembly.Load(assemblyName); } } 

请记住将以下依赖项添加到project.json文件中:

  "System.Runtime.Loader" "Microsoft.Extensions.DependencyModel" 

使用.net核心1.1 /标准1.6,我发现AssemblyLoader不可用,并且

  AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath) 

给了我一个“无法加载文件或程序集xxx”错误。

最后,下面的解决方案对我有用 – 纯粹是通过添加一个步骤来获取AssemblyName对象。 希望它可以帮助任何陷入困境的人:

  var assemblyName = AssemblyLoadContext.GetAssemblyName(assemblyPath);
 var assembly = Assembly.Load(assemblyName); 

@Rob,我可以让你的例子构建的唯一方法是将你的“myInstance”类型更改为动态

将类型保留为var确实允许代码构建,但是一旦我尝试使用运行时加载的程序集中的方法 ,我就会遇到编译器错误,例如myInstance不包含方法X. 我是新手,但将这种类型标记为动态,看起来似乎有道理。 如果在运行时加载类型,那么编译器如何validationmyInstance将包含方法X还是prop Y? 通过输入myInstance作为动态我相信你正在删除编译器检查,因此我可以得到构建和运行的例子。 不确定这是100%正确的方法(我不太了解你可能会建议使用动态有问题吗?)但这是我让它工作的唯一方法,而不必去创建我自己的麻烦AssemblyLoader(正确指出)。

所以…

 using System; using System.Runtime.Loader; namespace TestApp { class Program { static void Main(string[] args) { var myAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(@"C:\Documents\Visual Studio 2017\Projects\Foo\Foo\bin\Debug\netcoreapp2.0\Foo.dll"); var myType = myAssembly.GetType("Foo.FooClass"); dynamic myInstance = Activator.CreateInstance(myType); myInstance.UpperName("test"); } } } 

希望这可以帮助某人成为新手,我花了很多时间来确定为什么myInstance作为var没有方法X等Doh!