标签:
1. 程序集
程序集是自我描述的安装单位。
程序集清单:描述了程序集和引用它所需要的所有信息。
查看程序集:ildasm 工具
程序集特性:VS会生成 AssemblyInfo.cs 文件,描述程序集特性,用于配置程序集清单。
用“C#”高级编程的例子来学习创建与动态加载程序集:
public class CodeDriver { private string prefix = "using System;" + "public static class Driver" + "{" + "public static void run()" + "{"; private string postfix = "}" + "}"; public string CompileAndRun(string input, out bool hasError) { hasError = false; string returnData = null; CompilerResults results = null; using(var provider = new CSharpCodeProvider()) { var options = new CompilerParameters(); options.GenerateInMemory = true; var sb = new StringBuilder(); sb.Append(prefix); sb.Append(input); sb.Append(postfix); results = provider.CompileAssemblyFromSource(options, sb.ToString()); } if(results.Errors.HasErrors) { hasError = true; var errMessage = new StringBuilder(); foreach(CompilerError error in results.Errors) { errMessage.AppendFormat("{0} {1}", error.Line, error.ErrorText); } returnData = errMessage.ToString(); } else { TextWriter temp = Console.Out; var writer = new StringWriter(); Console.SetOut(writer); Type driverType = results.CompiledAssembly.GetType("Driver"); //通过反射在动态编译后的程序集中找到 Driver 这个静态类型 driverType.InvokeMember("Run", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, null); //通过反射调用 Driver 的静态方法 Run returnData = writer.ToString(); } return returnData; } }
值得注意的是:只要实例化了一种类型的程序集,或者使用了该类型的一个方法,就会自动加载所引用程序集。
另外,每次加载程序集,都会消耗越老越多的内存。如果要卸载程序集,就需要使用应用程序域。
2. 应用程序域
应用程序域-可以确保在同一进程中不能访问另外一个应用程序的内存;多个应用程序可以运行在一个进程的多个应用程序域中。
AppDomain 类用于创建与终止应用程序域,加载和卸载程序集。
示例:
程序集A:
public class Demo { public Demo(int val1, int val2) { Console.WriteLine("Constructor with the value {0}, {1} in domain" + "{2} called", val1, val2, AppDomain.CurrentDomain.FriendlyName); } } public class Program { static void Main() { Console.WriteLine("Main in domain {0} called", AppDomain.CurrentDomain.FriendlyName); Console.ReadLine(); } }
程序集B:
class AProgram { static void Main(string[] args) { AppDomain currentDomain = AppDomain.CurrentDomain; Console.WriteLine(currentDomain.FriendlyName); AppDomain secondDomain = AppDomain.CreateDomain("New Domain"); secondDomain.ExecuteAssembly("Delegate_Test.exe"); } }
启动程序集B--输出结果:
使用 ExecuteAssembly 应该是执行另外一个程序集中的可执行文件,如果不是可执行文件呢?
还有另外一种更常用的方式。程序集B:
class AProgram { static void Main(string[] args) { AppDomain currentDomain = AppDomain.CurrentDomain; Console.WriteLine(currentDomain.FriendlyName); AppDomain secondDomain = AppDomain.CreateDomain("New Domain"); //secondDomain.ExecuteAssembly("Delegate_Test.exe"); secondDomain.CreateInstance("Delegate_Test", "Assemblies_Test.Demo", true, BindingFlags.CreateInstance, null, new object[] { 2, 5 }, null, null); Console.ReadLine(); } }
public ObjectHandle CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes);
CreateInstance 返回的是 ObjectHandle,并不是实例。
进一步调用 Unwrap 方法返回背后的代理对象:
var results = secondDomain.CreateInstance("Delegate_Test", "Assemblies_Test.Demo", true, BindingFlags.CreateInstance, null, new object[] {2, 5}, null, null); var assemblies_Test = results.Unwrap() as Assemblies_Test.Demo; assemblies_Test.hello();
3. 程序集卸载
在主应用程序域中创建 新的应用程序域,并加载所需的程序集,在主应用程序域中,卸载新的域,就完成了程序集的卸载了。
标签:
原文地址:http://www.cnblogs.com/Daniel-Liang/p/5778151.html