看着博文之前,希望大家能看看 Allan. 的这篇文章。
http://www.cnblogs.com/zlgcool/archive/2008/10/12/1309616.html
之前逛园子时偶尔看到 Allan.这篇文章中提供了两种动态编译的方案,其中第一种方法由于卸载不太方便的确会导致内存方面的问题。而改良的第二种方法会将dll保存至bin目录,并通过加载这个dll,再调用dll中的方法,最后还有个删除dll的操作。这一系列操作势必会影响效率和浪费资源。我当时就想能否不简化这一系列的操作。所以才有了这篇博文,在这里首先感谢 Fish Li ,峰哥利用自己时间为园子里面的同志们解决问题,这种做法值得大家学习。
好了,开始说正文:
程序集的确是不能单独卸载,但程序域可以卸载,Allan. 的第二种方法可以借鉴修改。
先看看解决方案
autoCompiled:提供对源代码动态编译的功能
AppDomainTest:调用程序
Form1.cs:新建AppDomain、加载autoCompiled
RemoteLoader.cs:提供远程访问调用
Winform中引用autoCompiled项目。
大致的思路就是将整个代码的编译过程(Compiled.cs类)全部拿到AppDomain中执行,RemoteLoader.cs提供远程访问。
winform代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Reflection; namespace AppDomainTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string strSourceCode = @"using System; namespace Test { public class HelloWorld { public string GetTime(string strName) { return ""你好: "" + strName + "", 现在是北京时间: "" + System.DateTime.Now.ToString(); } } }"; object obj = CreateAppDomainExec(strSourceCode, "Test.HelloWorld", "GetTime"); MessageBox.Show(obj.ToString()); } /// <summary> /// 编译代码 /// </summary> /// <param name="strSourceCode">源代码</param> /// <param name="typeName">typeName,需要根据这个创建编译后的实例 namespace+className</param> /// <param name="FunctionName">调用的方法名</param> /// <returns>返回值</returns> public object CreateAppDomainExec(string strSourceCode, string typeName, string FunctionName) { AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationName = "TestAppDomain"; setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; AppDomain appDomain = AppDomain.CreateDomain("CreateDomain", null, setup); RemoteLoader remoteLoader = (RemoteLoader)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().GetName().FullName, typeof(RemoteLoader).FullName);//创建访问对象 remoteLoader.LoadAssembly("autoCompiled");//加载编译代码的程序集 object result = remoteLoader.CompiledExec(strSourceCode, typeName, FunctionName);//动态编译并执行 //卸载程序集 AppDomain.Unload(appDomain); appDomain = null; return result; } } }