AssemblyUnloadEventArgs本身不包含卸载的程序集信息,仅作为AppDomain卸载的通知信号,其设计目的是提供一个清理资源的时机而非传递数据;具体被卸载的程序集需通过自定义管理器在加载时记录,并在事件触发时通过sender参数获取对应AppDomain的上下文来查询。

坦白说,如果你期望从
AssemblyUnloadEventArgs
AppDomain
这个类存在的意义,更多是作为一个信号(signal),而非一个数据载体(data carrier)。当
AppDomain
AppDomain.AssemblyUnload
AssemblyUnloadEventArgs
AppDomain
sender
AppDomain
在我看来,
AssemblyUnloadEventArgs
AppDomain
它的主要用途是提供一个钩子(hook),让开发者有机会在
AppDomain
AppDomain
要监听
AppDomain
AppDomain.CurrentDomain.AssemblyUnload
AssemblyUnloadEventArgs
sender
AppDomain
using System;
using System.Reflection;
public class AppDomainMonitor
{
public static void Main(string[] args)
{
// 创建一个新的AppDomain
AppDomain newDomain = AppDomain.CreateDomain("MyTestDomain");
// 在新域中加载一个程序集(例如,加载当前执行的程序集)
// 实际应用中,你可能会通过Assembly.LoadFrom加载一个独立的DLL
string assemblyPath = Assembly.GetExecutingAssembly().Location;
newDomain.Load(AssemblyName.GetAssemblyName(assemblyPath));
// 订阅新域的AssemblyUnload事件
newDomain.AssemblyUnload += NewDomain_AssemblyUnload;
Console.WriteLine($"AppDomain '{newDomain.FriendlyName}' created and event subscribed.");
// 执行一些操作...
Console.WriteLine("Performing some operations in the new domain...");
// 卸载AppDomain
Console.WriteLine($"Unloading AppDomain '{newDomain.FriendlyName}'...");
AppDomain.Unload(newDomain);
Console.WriteLine("AppDomain unload initiated. Press any key to exit.");
Console.ReadKey();
}
private static void NewDomain_AssemblyUnload(object sender, AssemblyUnloadEventArgs e)
{
// 这里的 sender 就是即将被卸载的 AppDomain 实例
AppDomain unloadedDomain = sender as AppDomain;
if (unloadedDomain != null)
{
Console.WriteLine($"[Event Handler] AppDomain '{unloadedDomain.FriendlyName}' is about to unload.");
// 在这里执行清理逻辑
Console.WriteLine("[Event Handler] Performing cleanup operations...");
// 此时尝试访问 unloadedDomain.GetAssemblies() 可能会失败或返回不完整的结果
// 因为 AppDomain 已经处于卸载过程中
// Console.WriteLine($"[Event Handler] Assemblies in '{unloadedDomain.FriendlyName}':");
// foreach (var assembly in unloadedDomain.GetAssemblies())
// {
// Console.WriteLine($" - {assembly.FullName}");
// }
}
}
}通过
sender
AppDomain
AppDomain
AppDomain
AppDomain
sender
AppDomain
这是一个非常实际的需求,但也是
AssemblyUnloadEventArgs
AppDomain
AppDomain
这通常意味着,在你加载程序集的时候,就应该把它们记录下来。比如,在一个自定义的
AppDomain
List<Assembly>
List<string>
AssemblyUnload
sender
AppDomain
AppDomain
实现思路:
AppDomain
AppDomain
AppDomain.Load()
AppDomain.ExecuteAssembly()
AppDomain
AppDomain.AssemblyUnload
sender
AppDomain
AppDomain
using System;
using System.Collections.Generic;
using System.Reflection;
public class CustomAppDomainManager
{
private static Dictionary<AppDomain, List<string>> _loadedAssembliesMap = new Dictionary<AppDomain, List<string>>();
public AppDomain CreateAndMonitorDomain(string domainName)
{
AppDomain newDomain = AppDomain.CreateDomain(domainName);
newDomain.AssemblyLoad += NewDomain_AssemblyLoad; // 监听加载事件
newDomain.AssemblyUnload += NewDomain_AssemblyUnload; // 监听卸载事件
_loadedAssembliesMap[newDomain] = new List<string>(); // 初始化列表
Console.WriteLine($"Custom AppDomain '{domainName}' created.");
return newDomain;
}
public void LoadAssemblyIntoDomain(AppDomain domain, string assemblyPath)
{
// 假设这里是实际的加载逻辑,例如通过反射在远程域中执行
// 为了简化示例,我们只是模拟加载并记录
if (System.IO.File.Exists(assemblyPath))
{
// 在实际的跨域加载中,你需要使用 domain.Load() 或 domain.ExecuteAssembly()
// 这里我们只是记录路径
_loadedAssembliesMap[domain].Add(assemblyPath);
Console.WriteLine($" - Assembly '{assemblyPath}' simulated loaded into '{domain.FriendlyName}'.");
}
else
{
Console.WriteLine($" - Assembly path '{assemblyPath}' not found.");
}
}
public void UnloadDomain(AppDomain domain)
{
Console.WriteLine($"Initiating unload for AppDomain '{domain.FriendlyName}'...");
AppDomain.Unload(domain);
}
private static void NewDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
// 理论上,这里也可以记录,但通常我们更关心我们主动加载的
// 如果需要,可以在这里将 args.LoadedAssembly.FullName 加入 _loadedAssembliesMap[sender as AppDomain]
// 但通常我们只追踪我们主动加载的,避免系统程序集
// Console.WriteLine($"[Load Event] Assembly '{args.LoadedAssembly.FullName}' loaded into '{((AppDomain)sender).FriendlyName}'.");
}
private static void NewDomain_AssemblyUnload(object sender, AssemblyUnloadEventArgs e)
{
AppDomain unloadedDomain = sender as AppDomain;
if (unloadedDomain != null)
{
Console.WriteLine($"
[Unload Event] AppDomain '{unloadedDomain.FriendlyName}' is about to unload.");
if (_loadedAssembliesMap.TryGetValue(unloadedDomain, out List<string> assemblies))
{
Console.WriteLine($" Previously tracked assemblies in '{unloadedDomain.FriendlyName}':");
foreach (var assemblyPath in assemblies)
{
Console.WriteLine($" - {assemblyPath}");
}
_loadedAssembliesMap.Remove(unloadedDomain); // 清理追踪数据
}
else
{
Console.WriteLine($" No tracked assemblies found for '{unloadedDomain.FriendlyName}'.");
}
Console.WriteLine($"[Unload Event] Cleanup complete for '{unloadedDomain.FriendlyName}'.");
}
}
public static void Main(string[] args)
{
CustomAppDomainManager manager = new CustomAppDomainManager();
AppDomain domain1 = manager.CreateAndMonitorDomain("PluginDomain1");
manager.LoadAssemblyIntoDomain(domain1, "C:\Plugins\MyPluginA.dll");
manager.LoadAssemblyIntoDomain(domain1, "C:\Plugins\MyPluginB.dll");
AppDomain domain2 = manager.CreateAndMonitorDomain("PluginDomain2");
manager.LoadAssemblyIntoDomain(domain2, "C:\Plugins\MyPluginC.dll");
Console.WriteLine("
--- Simulating some work ---
");
System.Threading.Thread.Sleep(1000); // 模拟工作
manager.UnloadDomain(domain1);
System.Threading.Thread.Sleep(500); // 稍微等待
manager.UnloadDomain(domain2);
Console.WriteLine("
All domains unloaded. Press any key to exit.");
Console.ReadKey();
}
}通过这种方式,你可以在
AppDomain
AppDomain
AssemblyUnloadEventArgs
AppDomain
以上就是.NET的AssemblyUnloadEventArgs类如何获取卸载信息?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号