【发布时间】:2021-01-31 12:53:42
【问题描述】:
这是来自微软文档的代码。请注意代码中的cmets
class TestAssemblyLoadContext : AssemblyLoadContext
{
private AssemblyDependencyResolver _resolver;
public TestAssemblyLoadContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
}
protected override Assembly Load(AssemblyName name)
{
string assemblyPath = _resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
}
这是插件接口代码
public interface IPlugin
{
string result { get; }
}
这是加载和卸载方法(我从microsoft doc修改了代码)
private static string pluginPath = @"C:\PluginFolder\MyPlugin.dll"; //interface is IPlugin
private static TestAssemblyLoadContext talc; //the assemblyloadcontext
[MethodImpl(MethodImplOptions.NoInlining)]
static void LoadIt(string assemblyPath)
{
talc = new PluginFactory.TestAssemblyLoadContext(pluginPath); //create instance
Assembly a = talc.LoadFromAssemblyPath(assemblyPath);
//assemblyPath cant delete now because is loaded
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void UnloadIt()
{
talc.Unload();
for (int i = 0; i < 10; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
//if success unload, file on assemblyPath can success delete.
File.Delete(assemblyPath);
}
这是 wpf 程序代码的一部分
public MainWindow()
{
InitializeComponent();
LoadIt(pluginPath); //loaded assembly
UnloadIt(pluginPath); //success unload assembly, file assembly can delete.
}
private static TestAssemblyLoadContext talc;
LoadIt(){...}
UnloadIt(){...}
如果卸载代码不与加载代码一起
public MainWindow()
{
InitializeComponent();
LoadIt(pluginPath); //loaded assembly
}
private void Button_Click(object sender, RoutedEventArgs e)
{
UnloadIt(pluginPath); //unsuccessful. File assembly cant delete.
}
private static TestAssemblyLoadContext talc;
LoadIt(){...}
UnloadIt(){...}
但是如果在 Wpf 初始化函数“MainWindow()”或 wpf 应用程序事件中没有调用加载代码,例如Loaded 事件、ContentRendered 事件、Activated 事件,都会起作用。
public MainWindow()
{
InitializeComponent();
}
private void LoadButton_Click(object sender, RoutedEventArgs e)
{
LoadIt(pluginPath); //load plugin with button click event.
}
private void UnloadButton_Click(object sender, RoutedEventArgs e)
{
UnloadIt(pluginPath) //It successful unload, assembly file can be deleted.
}
private static TestAssemblyLoadContext talc;
LoadIt(){...}
UnloadIt(){...}
谁能告诉我为什么?这可能是一个错误吗?
您可以将代码复制到新的 wpf 程序中进行测试。我的运行时框架是 .Net 5。
【问题讨论】:
-
您是否可以多次调用 LoadIt?因为您每次调用它时都会覆盖
talc字段,因此会丢失先前的值... ,这意味着可以在不同的实例上调用 Unload 的后续调用,从而使旧上下文保持活动状态并锁定程序集文件 -
不,LoadIt() 在初始化函数中只被调用一次。您可以将这些代码复制到新的 wpf 应用程序并在 MainWindow() 中调用 LoadIt() 并在按钮单击事件中调用 UnloadIt()。这将得到我说的结果。无论如何,感谢您的评论。
标签: c# wpf .net-core .net-5 assembly-loading