(C#.Net Core)使用反射从外部程序集实例化类
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了(C#.Net Core)使用反射从外部程序集实例化类,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4780字,纯文字阅读大概需要7分钟。
内容图文
我目前正在尝试开发一种在外部项目中使用反射以编程方式运行测试类的方法.这是应该显示我的问题的简化代码块.
string pathToDLL = @"C:\Path\To\Test\Project\UnitTests.dll";
IEnumerable<Type> testClasses = assembly.GetExportedTypes();
Type testClass = testClasses.First();
object testClassInstance = assembly.CreateInstance(testClass.FullName);
此代码引发以下异常:
'assembly.CreateInstance(testClass.FullName)' threw an exception of type 'System.Reflection.TargetInvocationException'
Data: {System.Collections.ListDictionaryInternal}
HResult: -2146232828
HelpLink: null
InnerException: {System.IO.FileNotFoundException: Could not load file or assembly 'Project.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'Project.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
at Project.UnitTests.TestClass..ctor()}
Message: "Exception has been thrown by the target of an invocation."
Source: "System.Private.CoreLib"
StackTrace: " at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)\r\n at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)\r\n at System.Activator.CreateInstance(Type type, Boolean nonPublic)\r\n at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)\r\n at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)\r\n at System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)\r\n at System.Reflection.Assembly.CreateInstance(String typeName)"
在堆栈跟踪中指出“无法加载文件或程序集’Project.Core …’”.
该项目是目标DLL直接引用的项目(它已测试的项目).有谁知道为什么这将无法自动提取这些DLL?
我研究了解决此问题的方法:
1)这可能是dll的编译方式-可以更改此方式,因为我对此有控制权-当前是通过在解决方案级别运行dotnet build * / * / project.json来实现的.这样可以成功编译所有内容,并且所有相关的DLL似乎都已填充到bin文件夹中.我还研究了是否更改为dotnet publish或dotnet build * / * / project.json –configuration Release,尽管似乎都没有帮助.
2)我也研究过使用像Activator.CreateInstance这样的不同编译方法,同样没有骰子.
3)我似乎看不到将多个DLL加载到同一Assembly类中以便可以控制引用的方法.由于AppDomains已从.Net Core中删除,因此这看起来不太可能,尽管我可能会误解/在错误的地方查看.
如果我正在做的事情似乎不可能实现,那么有人知道是否可以使用其他方法来实现这种功能?即罗斯林?
解决方法:
我只是以为我将使用设法找到的解决方案来更新此问题,以防其他人遇到与我相同的问题.尽管我要感谢@EmrahSüngü为我指出正确的方向.
Emrah提请我注意以下事实:我需要导入要加载的DLL的依赖项,以调用存储在其中的类.一种方法是扩展app.config以便导入那些依赖项-但是我想在运行时执行此操作(对于在启动程序之前我不知道要运行的项目),所以我需要寻找另一种解决方案.
如果您不使用.NET Core,则这相对简单,因为AppDomains可用于加载所有依赖项并执行代码.但是,由于已经是removed from .NET Core,所以我需要找到另一个兼容的解决方案.
我开玩笑的想法是运行一个单独的进程(或Powershell),并更改工作目录,以便该进程在存储了所需所有依赖项的目录中运行.但是,我找不到一种可以使我对运行方法的结果做出反应的方法.
后来我研究了操纵AssemblyLoadContext类的方法,但是(at the time of writing)几乎没有关于该类的文档.我的确找到了这个答案,能够极大地帮助您……https://stackoverflow.com/a/37896162/6012159
为了使其正常工作,我确实必须进行一些更改,而不是每次都创建一个新的AssemblyLoader(这将导致在尝试调用Assembly中的方法时引发异常),而是每次都重用AssemblyLoader(已删除)这个问题).
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))
{
return this.LoadFromAssemblyPath(apiApplicationFileInfo.FullName);
}
}
return Assembly.Load(assemblyName);
}
}
可以用来加载这样的程序集:
string directory = @"C:\Path\To\Project\bin\Debug\netcoreapp1.0\publish\";
string pathToDLL = @"C:\Path\To\Project\bin\Debug\netcoreapp1.0\publish\project.dll";
AssemblyLoader al = new AssemblyLoader(directory);
Assembly assembly = al.LoadFromAssemblyPath(pathToDLL);
内容总结
以上是互联网集市为您收集整理的(C#.Net Core)使用反射从外部程序集实例化类全部内容,希望文章能够帮你解决(C#.Net Core)使用反射从外部程序集实例化类所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。