卸载程序集

卸载程序集

2015-04-16

 

Assembly没有Unload方法,那么程序如何在运行状态下卸载程序集呢?

可以用AppDomain.Unload方法。

想法一 (失败):

  1. create new Domain
  2. load assembly in new domain
  3. unload the new Domain

代码如下:

 1 using System;
 2 
 3 using System.Reflection;
 4 
 5 namespace UnloadAssembly
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             string file1 = @"C:\code\UnloadAssembly\Assembly1\bin\Debug\Assembly1.dll";
12             AppDomain appD = AppDomain.CreateDomain("#D1"); 
13             AssemblyName myAssemblyName1 = AssemblyName.GetAssemblyName(file1);
14             System.IO.File.Copy(file1, GetDestinateFile(file1), true);
15             appD.Load(myAssemblyName1);
16             string dName = appD.FriendlyName;
17             AppDomain.Unload(appD);
18         }
19 
20         public static string GetDestinateFile(string file)
21         {
22             return Environment.CurrentDirectory + @"\" + new System.IO.FileInfo(file).Name;
23         }
24     }
25 }
View Code

图1 想法一

想法二 [1](成功):

Create a class say class "B" derived by MarshalByRefObject

  • Write a method LoadAssembly({AssemblyPath}) in class "B". This function will only load that assembly and return void.
  • Write another method ExecuteMethod({ClassName, MethodName, Params}) in class "B" . This function execute the method (name passed in the parameter) of the loaded assembly.

Create a new class say class "A". This will be our main class from where we will start and execute the code.

  • write a main method in class "A" which will load class "B" in the new appdomain, and then call class B methods to load the assembly by passing the loadassembly method by passing assembly path and then by calling ExecuteMethod by passing method name and parameters.

 代码如下:

 1 using System;
 2 using System.Reflection;
 3 
 4 namespace UnloadAssembly
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             string file1 = @"C:\code\UnloadAssembly\Assembly1\bin\Debug\Assembly1.dll";
11             //Creating a new appdomain 
12             AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
13             //Create an instance of loader class in new appdomain 
14             AppDomain newDomain = AppDomain.CreateDomain("newDomain", AppDomain.CurrentDomain.Evidence, setup);
15 
16             System.Runtime.Remoting.ObjectHandle obj = newDomain.CreateInstance(typeof(LoadMyAssembly).Assembly.FullName, typeof(LoadMyAssembly).FullName);
17 
18             //As the object we are creating is from another appdomain hence we will get that object in wrapped format and hence in next step we have unwrappped it 
19             LoadMyAssembly loader = (LoadMyAssembly)obj.Unwrap();
20 
21             //Call loadassembly method so that the assembly will be loaded into the new appdomain amd the object will also remain in new appdomain only. 
22             loader.LoadAssembly(file1);
23 
24             //Call exceuteMethod and pass the name of the method from assembly and the parameters. 
25             loader.ExecuteStaticMethod("MyClass", "MyMethod", new object[] { 1 });
26 
27             //After the method has been executed call unload method of the appdomain. 
28             AppDomain.Unload(newDomain); 
29         }
30 
31         public sealed class LoadMyAssembly : MarshalByRefObject
32         {
33             private Assembly _assembly;
34             System.Type MyType = null;
35             object inst = null;
36             public override object InitializeLifetimeService()
37             {
38                 return null;
39             }
40 
41             public void LoadAssembly(string path)
42             {
43                 _assembly = Assembly.Load(AssemblyName.GetAssemblyName(path));
44             }
45 
46             public object ExecuteStaticMethod(string className, string methodName, params object[] parameters)
47             {
48                 foreach (System.Type type in _assembly.GetTypes())
49                 {
50                     if (String.Compare(type.Name, className, true) == 0)
51                     {
52                         MyType = type;
53                         inst = _assembly.CreateInstance(type.FullName);
54 
55                         break;
56                     }
57                 }
58                 MethodInfo MyMethod = MyType.GetMethod(methodName, new Type[] { typeof(int) });
59                 MyMethod.Invoke(inst, BindingFlags.InvokeMethod, null, parameters, null);
60                 return null;
61             }
62         }
63 
64         public static string GetDestinateFile(string file)
65         {
66             return Environment.CurrentDirectory + @"\" + new System.IO.FileInfo(file).Name;
67         }
68     }
69 }
View Code

被加载的assembly代码如下:

1     public class MyClass
2     {
3         public string MyMethod(int i)
4         {
5             return (i * 2).ToString();
6         }
7     }
View Code

参考

[1] How to Unload an Assembly Loaded Dynamically Using Reflection

posted @ 2015-04-16 17:53  明-Ming  阅读(388)  评论(1编辑  收藏  举报