卸载程序集
2015-04-16
Assembly没有Unload方法,那么程序如何在运行状态下卸载程序集呢?
可以用AppDomain.Unload方法。
想法一 (失败):
- create new Domain
- load assembly in new domain
- 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 }
图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 }
被加载的assembly代码如下:
1 public class MyClass 2 { 3 public string MyMethod(int i) 4 { 5 return (i * 2).ToString(); 6 } 7 }
参考
[1] How to Unload an Assembly Loaded Dynamically Using Reflection