==============================================动态编译程序思路
* 0,把C#以字符串的方式放在string对象里
* 1,实例化一个C#编译器:CSharpCodeProvider
* 2,创建编译器环境(并配置环境):CompilerParameters
* 3,开始编译:ccp.CompileAssemblyFromSource(cp, abc);
* 4,返回编译结果:CompilerResults
* 【5,可以使用反射调用该程序集】
==============================================什么是程序域?
在.net技术之前,进程做为应用程序独立的边界,
.net体系结构中,应用程序有一个新的边界,就是程序域。可以合理分配对象在不同的程序域中,
可以对程序域进行卸载
==============================================程序域的作用
如果程序集是动态加载的,且需要在使用完后卸载程序集,应用程序域就非常有
用。 在主应用程序域中,不能删除已加载的程序集,但可以终止应用程序域,在该应
用程序域中载的所有程序集都会从内存中清除。
==============================================例子:
--------------------------------------CompileType.cs(枚举文件)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AppDomainDemo { public enum CompileType { Console,//控制台输出 File//输出文件 } }
--------------------------------------CompileCode.cs(动态编译程序代码类)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Reflection; using Microsoft.CSharp;//提供对 C# 代码生成器和代码编译器的实例的访问。 using System.CodeDom.Compiler;//用途是对所支持编程语言的源代码的生成和编译进行管理 namespace AppDomainDemo { //MarshalByRefObject:跨域访问必须要继承此类 public class CompileCode : MarshalByRefObject { public string CompileCodeGo(string input, CompileType ct, out bool IsError) { StringBuilder sb1 = new StringBuilder(); sb1.Append("using System;"); sb1.Append("using System.Windows.Forms;"); sb1.Append("public class Program{public static void Main(string[] args){"); StringBuilder sb2 = new StringBuilder(); sb2.Append("}"); sb2.Append("public void aa(){"); string bottom = "}}"; //编译器 CSharpCodeProvider ccp = new CSharpCodeProvider(); //编译参数配置 CompilerParameters cp = new CompilerParameters(); //编译结果 CompilerResults cr; //控制台输出 if (ct == CompileType.Console) { //设置是否在内存中生成输出 cp.GenerateInMemory = true; } else//编译为可执行文件 { //是否是可执行文件 cp.GenerateExecutable = true; //配置输出文件路径 cp.OutputAssembly = Directory.GetCurrentDirectory() + "/" + DateTime.Now.ToString("yyyyMMhhddmmss") + ".exe"; } //引用程序集 cp.ReferencedAssemblies.Add("System.Windows.Forms.dll"); //编译 cr = ccp.CompileAssemblyFromSource(cp, sb1.ToString() + input + sb2.ToString() + input + bottom); if (cr.Errors.HasErrors)//编辑结果出现异常 { IsError = true; string error = ""; for (int i = 0; i < cr.Errors.Count; i++) { error += string.Format("影响行数:{0},错误信息:{1}\r\n", cr.Errors[i].Line.ToString(), cr.Errors[i].ErrorText); } return error; } else { IsError = false; //用于接受控制台输出的信息 StringWriter sw = new StringWriter(); Console.SetOut(sw); //获取编译的程序集[反射] Assembly asb = cr.CompiledAssembly; //获取类 Type t = asb.GetType("Program"); //非静态方法需要实例化类 object o = Activator.CreateInstance(t); //获取方法 MethodInfo m = t.GetMethod("aa"); //执行方法 m.Invoke(o, null); //返回控制台输出的结果 return sw.ToString(); } } } }
--------------------------------------AppDomainCode.cs(创建卸载程序域类)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AppDomainDemo { public class AppDomainCode { public string AppDomainCodeGo(string input, CompileType ct, out bool IsError) { //创建程序域 AppDomain app = AppDomain.CreateDomain("zhangdi"); //创建制定类型的实例 CompileCode cc = (CompileCode)app.CreateInstanceAndUnwrap("AppDomainDemo", "AppDomainDemo.CompileCode"); string result= cc.CompileCodeGo(input, ct, out IsError); //卸载程序域 AppDomain.Unload(app); return result; } } }
--------------------------------------Form1.cs(窗体后台程序)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace AppDomainDemo { /* ************************************* *代码不能为Console.ReadKey(); *点击 点击我输出控制台 按钮【出现错误:调用的目标发生了异常】 *这个错误我找了好几天,坑爹 ************************************* */ public partial class Form1 : Form { public Form1() { InitializeComponent(); } string str = "Console.WriteLine(\"aasdasd\");Console.ReadLine();"; /// <summary> /// 点我输出控制台 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnConsole_Click(object sender, EventArgs e) { AppDomainCode adc = new AppDomainCode(); bool iserror; string result = adc.AppDomainCodeGo(str, CompileType.Console, out iserror); richTextBox1.Text = result; } /// <summary> /// 点我输出可执行文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnFile_Click(object sender, EventArgs e) { AppDomainCode adc = new AppDomainCode(); bool iserror; string result = adc.AppDomainCodeGo(str, CompileType.File, out iserror); richTextBox1.Text = result; } } }