C#中如何实现代码解释器

这篇文章主要介绍C#中如何实现代码解释器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

1、C#代码解释器简介

能够动态执行 C#代码是一件很酷的功能,比如,我们可以在控制台中输入一行 C#代码,然后程序自动编译并执行这一行代码,将结果显示给我们。这差不多就是一个最简单的 C#代码解释器了。

动态执行 C#代码又是一件很有用的功能,比如,我们可以将某些代码写在某个文件之中,由程序集在执行时进行加载,改变这些代码不用中止程序,当程序再次加载这些代码时,就自动执行的是新代码了。

2、简单的 C#代码解释器

  1. usingSystem;  

  2. usingSystem.Collections.Generic;  

  3. usingSystem.Reflection;  

  4. usingSystem.Globalization;  

  5. usingMicrosoft.CSharp;  

  6. usingSystem.CodeDom;  

  7. usingSystem.CodeDom.Compiler;  

  8. usingSystem.Text;  

  9. usingSystem.IO;  

  10. usingSystem.Xml;  

  11.  

  12. namespaceTest  

  13. {  

  14. classProgram  

  15. {  

  16. staticvoidMain(string[]args)  

  17. {  

  18. Console.Write(">>");  

  19. Stringcmd;  

  20. Contextcxt=newContext();  

  21. while((cmd=Console.ReadLine().Trim())!="exit")  

  22. {  

  23. if(!String.IsNullOrEmpty(cmd))  

  24. {  

  25. Console.WriteLine();  

  26. cxt.Invoke(cmd);  

  27. }  

  28. Console.Write("/n>>");  

  29. }  

  30. }  

  31. }  

  32.  

  33. publicclassContext  

  34. {  

  35. publicCSharpCodeProviderCodeProvider{get;set;}  

  36. publicIDictionary<String,Assembly>Assemblys{get;set;}  

  37.  

  38. publicContext()  

  39. {  

  40. CodeProvider=newCSharpCodeProvider(newDictionary<string,string>()
    {{"CompilerVersion","v3.5"}});  

  41. Assemblys=newDictionary<String,Assembly>();  

  42. Assembly[]al=AppDomain.CurrentDomain.GetAssemblies();  

  43. foreach(Assemblyainal)  

  44. {  

  45. AddAssembly(a);  

  46. }  

  47. AppDomain.CurrentDomain.AssemblyLoad+=newAssemblyLoadEventHandler
    (CurrentDomain_AssemblyLoad);  

  48. }  

  49.  

  50. privatevoidAddAssembly(Assemblya)  

  51. {  

  52. if(a!=null)  

  53. {  

  54. Assemblys.Add(a.FullName,a);  

  55. }  

  56. }  

  57.  

  58. voidCurrentDomain_AssemblyLoad(objectsender,AssemblyLoadEventArgsargs)  

  59. {  

  60. Assemblya=args.LoadedAssembly;  

  61. if(!Assemblys.ContainsKey(a.FullName))  

  62. {  

  63. AddAssembly(a);  

  64. }  

  65. }  

  66.  

  67. publicCompilerParametersCreateCompilerParameters()  

  68. {  

  69. CompilerParameterscp=newCompilerParameters();  

  70. cp.GenerateExecutable=false;  

  71. cp.GenerateInMemory=true;  

  72. if(Assemblys!=null)  

  73. {  

  74. foreach(AssemblyainAssemblys.Values)  

  75. {  

  76. cp.ReferencedAssemblies.Add(a.Location);  

  77. }  

  78. }  

  79. returncp;  

  80. }  

  81.  

  82. publicvoidInvoke(Stringcmd)  

  83. {  

  84. StringinputCmdString=cmd.Trim();  

  85. if(String.IsNullOrEmpty(inputCmdString))return;  

  86.  

  87. StringfullCmd=BuildFullCmd(inputCmdString);  

  88.  

  89. CompilerResultscr=CodeProvider.CompileAssemblyFromSource
    (CreateCompilerParameters(),fullCmd);  

  90.  

  91. if(cr.Errors.HasErrors)  

  92. {  

  93. BooleanrecompileSwitch=true;  

  94.  

  95. foreach(CompilerErrorerrincr.Errors)  

  96. {  

  97. //CS0201:Onlyassignment,call,increment,decrement,andnewobjectexpressionscanbe  

  98. //usedasastatement  

  99. if(!err.ErrorNumber.Equals("CS0201"))  

  100. {  

  101. recompileSwitch=false;  

  102. break;  

  103. }  

  104. }  

  105.  

  106. //重新编译  

  107. if(recompileSwitch)  

  108. {  

  109. StringdynaName="TempArg_Dynamic_"+DateTime.Now.Ticks.ToString();  

  110. inputCmdString=String.Format("var{0}=",dynaName)+inputCmdString;  

  111. inputCmdString+=";/nSystem.Console.WriteLine("+dynaName+");";  

  112.  

  113. fullCmd=BuildFullCmd(inputCmdString);  

  114. cr=CodeProvider.CompileAssemblyFromSource(CreateCompilerParameters(),fullCmd);  

  115. }  

  116.  

  117. if(cr.Errors.HasErrors)  

  118. {  

  119. Console.WriteLine("编译错误:");  

  120. foreach(CompilerErrorerrincr.Errors)  

  121. {  

  122. Console.WriteLine(err.ErrorNumber);  

  123. Console.WriteLine(err.ErrorText);  

  124. }  

  125.  

  126. return;  

  127. }  

  128. }  

  129.  

  130. Assemblyassem=cr.CompiledAssembly;  

  131. ObjectdynamicObject=assem.CreateInstance("Test.DynamicClass");  

  132. Typet=assem.GetType("Test.DynamicClass");  

  133. MethodInfominfo=t.GetMethod("MethodInstance");  

  134. minfo.Invoke(dynamicObject,null);  

  135. }  

  136.  

  137. privateStringBuildFullCmd(StringinputCmdString)  

  138. {  

  139. StringStringfullCmd=String.Empty;  

  140.  

  141. fullCmd+=@"  

  142. namespaceTest  

  143. {  

  144. publicclassDynamicClass  

  145. {  

  146. publicvoidMethodInstance()  

  147. {  

  148. "+inputCmdString+@";  

  149. }  

  150. }  

  151. }";  

  152. returnfullCmd;  

  153. }  

  154. }  

以上是“C#中如何实现代码解释器”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/tech/dev/230737.html

(0)
上一篇 2022年1月15日 20:39
下一篇 2022年1月15日 20:39

相关推荐

发表回复

登录后才能评论