asp.net 动态加载与卸载程序集的尝试(没有成功)欢迎解决的朋友留言告知
参考 C#.Net 如何动态加载与卸载程序集(.dll或者.exe)0-------通过应用程序域AppDomain加载和卸载程序集 - 龙骑科技 - 博客园 (cnblogs.com)
大概意思是微软的.NET运行不支持直接卸载应用程序集,因为一旦加载程序集,即使是动态加载就会给该程序集加载到当前正在运行的主线程上,如果想卸载程序集就需要停掉当前主线程,所以不能这么操作。
文章介绍为了实现动态加载和卸载,可以通过AppDomain创建子程序集,需要卸载时就卸载掉整个AppDomain,
但是不知道什么原因,在执行AppDomain加载子程序集时跟断点明明已经拿到了dll文件的程序集,但在返回的时候会报没有序列化的异常。
接下来我给我的代码运行代码贴出来看一下
首先创建Plugin1类库项目并创建One.cs文件内容如下发布出文件为Plugin1.dll文件
using System; namespace Plugin1 { [Serializable] public class One : MarshalByRefObject { public string GetName(string name) { return "输出当前名字:" + name; } } }
然后创建新的测试项目首先创建类ObjectLoader1.cs文件代码如下
1 using System; 2 using System.Collections; 3 using System.Reflection; 4 5 /// <summary> 6 /// ObjectLoader 的摘要说明 7 /// </summary> 8 public class ObjectLoader1:IDisposable 9 { 10 protected Hashtable domains = new Hashtable(); 11 public ObjectLoader1() { } 12 public object GetObject(string dllName,string typeName,object[] constructorParms) 13 { 14 AssemblyLoader al = null; 15 object o = null; 16 if (al == null) 17 { 18 AppDomainSetup setup = new AppDomainSetup(); 19 setup.ShadowCopyFiles = "true"; 20 AppDomain domain = AppDomain.CreateDomain(dllName, null, setup); 21 domains.Add(dllName, domain); 22 object[] parms = { dllName }; 23 BindingFlags bindings = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public; 24 try 25 { 26 var ww = CYQ.Data.AppConst.WebRootPath; 27 var currAssembly=Assembly.GetExecutingAssembly(); 28 al = (AssemblyLoader)domain.CreateInstanceFromAndUnwrap(currAssembly.CodeBase, "AssemblyLoader", true, bindings, null, parms, null, null); 29 } 30 catch (Exception e1) 31 { 32 throw new Exception(); 33 } 34 } 35 if (al != null) 36 { 37 o = al.GetAssembly(); 38 } 39 return o; 40 } 41 public void Unload(string dllName) 42 { 43 if (domains.ContainsKey(dllName)) 44 { 45 AppDomain domain = (AppDomain)domains[dllName]; 46 AppDomain.Unload(domain); 47 domains.Remove(dllName); 48 } 49 } 50 ~ObjectLoader1() { 51 dispose(false); 52 } 53 public void Dispose() { 54 dispose(true); 55 } 56 private void dispose(bool disposing) 57 { 58 if (disposing) 59 { 60 foreach(object o in domains.Keys) 61 { 62 string dllName = o.ToString(); 63 Unload(dllName); 64 } 65 domains.Clear(); 66 } 67 } 68 } 69 public class AssemblyLoadFailureException1 : Exception 70 { 71 public AssemblyLoadFailureException1() : base() 72 { 73 } 74 75 public override string Message 76 { 77 get 78 { 79 return "Assembly Load Failure"; 80 } 81 } 82 83 } 84 public class AssemblyLoader1 : MarshalByRefObject, IDisposable 85 { 86 private Assembly a = null; 87 public AssemblyLoader1() { } 88 public AssemblyLoader1(string fullPath) { 89 if (a == null) 90 { 91 a = Assembly.LoadFrom(fullPath); 92 } 93 } 94 ~AssemblyLoader1() { 95 dispose(false); 96 } 97 public void Dispose() 98 { 99 dispose(true); 100 } 101 private void dispose(bool disposing) 102 { 103 if (disposing) 104 { 105 a = null; 106 GC.Collect(); 107 GC.WaitForPendingFinalizers(); 108 GC.Collect(0); 109 } 110 } 111 public Assembly GetAssembly() 112 { 113 return a; 114 } 115 public Assembly LoadAssembly(string dllName) 116 { 117 try 118 { 119 a = Assembly.LoadFrom(dllName); 120 return a; 121 } 122 catch (Exception) 123 { 124 throw new AssemblyLoadFailureException1(); 125 } 126 } 127 }
然后调用代码
1 var ww = AppDomain.CurrentDomain.BaseDirectory; 2 ObjectLoader1 ol = new ObjectLoader1(); 3 var o = ol.GetObject(ww + "Plugin1.dll", "Plugin1.One", new object[] { });
断点ObjectLoader1.cs文件的37行,和ObjectLoader1.cs的113行,F10执行,会发现在执行完113行之后代码正常返回,但紧跟着回到第37行时,代码抛出异常
System.IO.FileNotFoundException:“未能加载文件或程序集“Plugin1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项。系统找不到指定的
接下来就不知道如何解决了,只能搁置到这里了,如果哪位大神有解决方案希望可以告知!
第二种方法,这个是通过大模型提供的方法
代码如下
AppDomainLoader.cs文件
1 using System; 2 using System.Reflection; 3 4 /// <summary> 5 /// AppDomainLoader 的摘要说明 6 /// </summary> 7 public class AppDomainLoader 8 { 9 public void One(string dllName) 10 { 11 // 创建新的 AppDomain 12 AppDomain domain = AppDomain.CreateDomain("MyDomain"); 13 14 var ww = CYQ.Data.AppConst.WebRootPath; 15 // 要加载的程序集的文件路径 16 string dllPath = ww + "Plugin1.dll"; 17 dllPath = dllName; 18 try 19 { 20 var str= AssemblyName.GetAssemblyName(dllPath); 21 22 //object[] parms = { dllPath }; 23 //BindingFlags bindings = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public; 24 //var al = domain.CreateInstanceFromAndUnwrap(str.CodeBase, "Plugin1.One", true, bindings, null, parms, null, null); 25 // 加载程序集到 AppDomain 26 Assembly assembly = domain.Load(str); 27 28 // 获取类型 29 Type type = assembly.GetType("Plugin1.One"); 30 31 // 实例化对象 32 if (type != null) 33 { 34 object instance = Activator.CreateInstance(type); 35 36 // 在这里可以调用对象的方法或访问其属性 37 // 例如: 38 MethodInfo method = type.GetMethod("GetName"); 39 if (method != null) 40 { 41 method.Invoke(instance, new[] { "这是名字"}); 42 } 43 else 44 { 45 throw new Exception(); 46 } 47 } 48 else 49 { 50 throw new Exception(); 51 } 52 } 53 catch (Exception ex) 54 { 55 throw new Exception(); 56 } 57 finally 58 { 59 // 卸载 AppDomain 以释放程序集和资源 60 AppDomain.Unload(domain); 61 } 62 63 } 64 }
外部调用方法如下
1 var ww = AppDomain.CurrentDomain.BaseDirectory; 2 var adl = new AppDomainLoader(); 3 adl.One(ww + "Plugin1.dll");
这个同样在执行加载程序集时报错,
AppDomainLoader.cs文件的22,23,24行注释可以打开运行测试,也报错,因为知识有限,不知道如何解决
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南