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行注释可以打开运行测试,也报错,因为知识有限,不知道如何解决

 

posted @ 2024-07-17 17:25  uxinxin  阅读(6)  评论(0编辑  收藏  举报