卸载程序集
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 : MarshalByRefObject32 {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 MyClass2 {3 public string MyMethod(int i)4 {5 return (i * 2).ToString();6 }7 }
参考
[1]