问题描述
我正在.Net Core平台上制作一个控制台应用程序,并且想知道,如何使用C#动态功能加载程序集(.dll文件)并实例化类?它似乎与.Net 4.X有很大不同,并且没有真正记录在文档中。
I'm making a console app on .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...
例如,假设我有一个类库(.Net Core),它仅具有一个类:
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;
}
}
}
因此dll的名称文件将是 MyClassLib.dll
,位于 /dlls/MyClassLib.dll
中。
So the name of the dll file would be MyClassLib.dll
and its located in /dlls/MyClassLib.dll
.
现在,我想将其加载到简单的控制台应用程序(.Net Core)中,并实例化 Sample
类,并使用的动态功能调用方法以下控制台应用中的C#:
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
}
}
}
注意:
.Net Core我的意思是RC2版本。
Note:By .Net Core I mean RC2 version.
推荐答案
不确定这是否是最好的方法,但这是我想出的:
Not sure if it's the best way to do it but here's what I came up with:
(仅在.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
是类型名。
MyClassLib.SampleClasses
is the namespace and Sample
is the type aka class name.
执行后,它将尝试将 SampleClassLib.dll
编译的类库加载到内存中,并使控制台应用程序可以访问 MyClassLib .SampleClasses.Sample
(看看问题),然后我的应用程序调用方法 SayHello()
并将 John Doe作为名称传递给它,因此该程序将打印:
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:
你好,约翰·道伊
快速说明:
方法 Load
的覆盖无关紧要您最好将其内容替换为并抛出新的NotImplementedException()
,它不应影响我们所关心的任何事情。
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.
这篇关于如何在.net核心控制台应用程序的文件夹中加载程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!