==============================================动态编译程序思路
* 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;
}
}
}