如何解决如何从 AppDomain 实例化 IModule 继承类?
我在这里有点困惑,没有从谷歌那里得到太多帮助。这是我想要做的:
public Boolean LoadModule(String moduleHandle)//name of module MUST match its .dll name. Name of AppDomain is the same as the Handle.
{
try
{
AppDomain moduleDomain = AppDomain.CreateDomain(moduleHandle);
String pathToDll = @"C:\IModules.dll"; //Full path to dll you want to load
Type moduleType = typeof(IModule);
IModule loadedModule = (IModule)moduleDomain.CreateInstanceFromAndUnwrap(pathToDll,moduleType.FullName);
ModuleList.Add(loadedModule,moduleDomain);
broadcast("Module loaded: " + moduleHandle,ModuleManagerHandle);
return true;
}
catch (Exception e)
{
//console writeline the error? probably cant
OutputBox.AppendText(e.ToString() + Environment.NewLine);
return false;
}
}
我以为我终于弄明白了,但是当我尝试实例化 IModule(在本例中为 ConsoleModule)时,出现以下错误: System.MissingMethodException: 未找到类型“IModules.IModule”的构造函数。
我认为这意味着我需要一个构造函数,就好像这是一个在此函数调用中实例化自身的类对象,但我不能让接口具有构造函数。 我已经看到其他线程提出了解决这个问题的方法,但他们使用程序集而不是 appdomain,这会破坏卸载模块的能力。我担心如果没有卸载模块的能力,应用程序会随着时间的推移而遭受内存膨胀。
最终目标是能够编写一个模块,让程序运行并在运行时加载/卸载模块,而无需对核心程序进行任何更改,并随时随地添加功能。 任何人都知道解决方法或处理动态模块加载和卸载的更好方法?
解决方法
这是在 .NET 5.0 AssemblyLoadContext 中修复的:
var basePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
AssemblyLoadContext moduleAssemblyLoadContext = new AssemblyLoadContext(moduleHandle,true);
Assembly moduleAssembly = moduleAssemblyLoadContext.LoadFromAssemblyPath($"{basePath}\\{moduleHandle}.dll");
Type[] types = moduleAssembly.GetTypes();
foreach (Type type in types)
{
// Does this class support the transport interface?
Type typeModule = type.GetInterface("IModule");
if (typeModule == null)
{
// Not supported.
continue;
}
// This class supports the interface. Instantiate it.
IModule loadedModule = moduleAssembly.CreateInstance(type.FullName) as IModule;
if (loadedModule != null)
{
loadedModule.LoadedModule(this);
ModuleList.Add(loadedModule,moduleAssemblyLoadContext);
Broadcast("Module loaded: " + moduleHandle,ModuleManagerHandle);
OutputTextBox.AppendText(moduleHandle + " was loaded." + Environment.NewLine);
// Successfully created the interface. We are done.
return true;
}
}
return false;
无法再找到源代码,但发现它正在寻找相关问题(无论如何您都可以在 MSDN 上找到它)。这成功地将程序集加载和卸载到它们的上下文中。用户必须将 isCollectible 值设置为 TRUE 才能启用完全卸载。
我遇到的唯一问题是 .NET 5.0 与自身不兼容,但在尝试加载程序集时,作为 .NET 5.0 加载到 .NET 5.0 程序中的库会给出 BadImageFormatException。要修复,请将 LIBRARY 设置为下一个最新的目标框架(在我的例子中是 .NET Core 3.1)并将新编译的 dll 移动到它所到的任何位置,应用程序应该使用新的 dll 运行。
,错误告诉您没有找到类型 IModule
的默认(空)构造函数。由于 IModule 是一个接口,该消息似乎有些道理。
结果:实例化一个实现 class
的 IModule
。一个接口永远不能单独实现。
要实例化该类,只需更改一行:
Type moduleType = typeof(ClassThatImplementIModule);
您仍然可以将实例转换为 IModule
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。