You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
4.5 KiB

using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Shentun.Peis.DiagnosisFunctions
{
public class CodeBuilder
{
private static List<MetadataReference> _references = new List<MetadataReference>();
/// <summary>
/// 编译前的初始化,只需要一次
/// </summary>
/// <returns></returns>
static CodeBuilder()
{
_references = new List<MetadataReference>();
// 元数据引用
if (_references == null || _references.Count == 0)
{
_references = new List<MetadataReference>()
{
MetadataReference.CreateFromFile(typeof(System.Uri).Assembly.Location),
MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location),
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(System.IO.File).Assembly.Location),
MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location),
MetadataReference.CreateFromFile(Assembly.Load("System.Collections").Location),
MetadataReference.CreateFromFile(Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory+"Shentun.Peis.Application.dll").Location),
};
}
//Assembly as1 = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "mscorlib.dll");
//MetadataReference metadataReference = _references.Find((o => o.Display.Contains("mscorlib.dll")));
//if (_references.Find((o => o.Display.Contains("mscorlib.dll"))) == null)
//{
// _references.Add(MetadataReference.CreateFromFile(as1.Location));
//}
}
//public CodeBuilder()
//{
//}
//public Assembly CreateCode(string code)
//{
// //var domain = new NatashaDomain("key");
// //var domain = DomainManagement.Random();
// NatashaManagement.Preheating();
// Path.GetRandomFileName();
// using (DomainManagement.Create("myDomain").CreateScope())
// {
// AssemblyCSharpBuilder builder = new AssemblyCSharpBuilder();
// builder.Add(code);
// var func = builder.GetDelegateFromShortName<Func<string>>("Test", "GetName");
// }
// return myAssembly;
//}
public Assembly GenerateAssemblyFromCode(string code)
{
Assembly assembly = null;
// 丛代码中转换表达式树
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
// 随机程序集名称
//string assemblyName = Path.GetRandomFileName();
var assemblyName = "_" + Guid.NewGuid().ToString("D");
//assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
//assemblyName = "Shentun.Peis.Application";
var syntaxTrees = new SyntaxTree[] { syntaxTree };
// 引用
var references = _references;// referencedAssemblies.Select(x => MetadataReference.CreateFromFile(x.Location));
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
// 创建编译对象
CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, syntaxTrees, references, options);
using (var ms = new MemoryStream())
{
// 将编译好的IL代码放入内存流
EmitResult result = compilation.Emit(ms);
// 编译失败,提示
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
}
else
{
// 编译成功,从内存中加载编译好的程序集
ms.Seek(0, SeekOrigin.Begin);
assembly = Assembly.Load(ms.ToArray());
}
}
return assembly;
}
}
}