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

2 years ago
2 years ago
2 years ago
  1. using Microsoft.CodeAnalysis.CSharp;
  2. using Microsoft.CodeAnalysis.Emit;
  3. using Microsoft.CodeAnalysis;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Reflection;
  9. namespace Shentun.Peis.DiagnosisFunctions
  10. {
  11. public class CodeBuilder
  12. {
  13. private static List<MetadataReference> _references = new List<MetadataReference>();
  14. /// <summary>
  15. /// 编译前的初始化,只需要一次
  16. /// </summary>
  17. /// <returns></returns>
  18. static CodeBuilder()
  19. {
  20. _references = new List<MetadataReference>();
  21. // 元数据引用
  22. if (_references == null || _references.Count == 0)
  23. {
  24. _references = new List<MetadataReference>()
  25. {
  26. MetadataReference.CreateFromFile(typeof(System.Uri).Assembly.Location),
  27. MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location),
  28. MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
  29. MetadataReference.CreateFromFile(typeof(System.IO.File).Assembly.Location),
  30. MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location),
  31. MetadataReference.CreateFromFile(Assembly.Load("System.Collections").Location),
  32. MetadataReference.CreateFromFile(Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory+"Shentun.Peis.Application.dll").Location),
  33. };
  34. }
  35. //Assembly as1 = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "mscorlib.dll");
  36. //MetadataReference metadataReference = _references.Find((o => o.Display.Contains("mscorlib.dll")));
  37. //if (_references.Find((o => o.Display.Contains("mscorlib.dll"))) == null)
  38. //{
  39. // _references.Add(MetadataReference.CreateFromFile(as1.Location));
  40. //}
  41. }
  42. //public CodeBuilder()
  43. //{
  44. //}
  45. //public Assembly CreateCode(string code)
  46. //{
  47. // //var domain = new NatashaDomain("key");
  48. // //var domain = DomainManagement.Random();
  49. // NatashaManagement.Preheating();
  50. // Path.GetRandomFileName();
  51. // using (DomainManagement.Create("myDomain").CreateScope())
  52. // {
  53. // AssemblyCSharpBuilder builder = new AssemblyCSharpBuilder();
  54. // builder.Add(code);
  55. // var func = builder.GetDelegateFromShortName<Func<string>>("Test", "GetName");
  56. // }
  57. // return myAssembly;
  58. //}
  59. public Assembly GenerateAssemblyFromCode(string code)
  60. {
  61. Assembly assembly = null;
  62. // 丛代码中转换表达式树
  63. SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
  64. // 随机程序集名称
  65. //string assemblyName = Path.GetRandomFileName();
  66. var assemblyName = "_" + Guid.NewGuid().ToString("D");
  67. //assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
  68. //assemblyName = "Shentun.Peis.Application";
  69. var syntaxTrees = new SyntaxTree[] { syntaxTree };
  70. // 引用
  71. var references = _references;// referencedAssemblies.Select(x => MetadataReference.CreateFromFile(x.Location));
  72. var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
  73. // 创建编译对象
  74. CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, syntaxTrees, references, options);
  75. using (var ms = new MemoryStream())
  76. {
  77. // 将编译好的IL代码放入内存流
  78. EmitResult result = compilation.Emit(ms);
  79. // 编译失败,提示
  80. if (!result.Success)
  81. {
  82. IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
  83. diagnostic.IsWarningAsError ||
  84. diagnostic.Severity == DiagnosticSeverity.Error);
  85. foreach (Diagnostic diagnostic in failures)
  86. {
  87. Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
  88. }
  89. }
  90. else
  91. {
  92. // 编译成功,从内存中加载编译好的程序集
  93. ms.Seek(0, SeekOrigin.Begin);
  94. assembly = Assembly.Load(ms.ToArray());
  95. }
  96. }
  97. return assembly;
  98. }
  99. }
  100. }