简单的C#代码解释器

开发 后端
本文介绍简单的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. }  

【编辑推荐】

  1. 分析C#不安全代码
  2. 浅析C#调用ImageAnimator
  3. C#连接Access、SQL Server数据库
  4. 浅谈C#固定的和活动的变量
  5. 介绍C#中的值类型
责任编辑:佚名 来源: 博客园
相关推荐

2009-08-13 17:36:54

编译C#代码

2009-08-31 17:53:20

C#实现索引器

2009-08-06 15:12:22

C#异常机制

2009-08-31 14:54:35

C#对象浏览器

2009-09-01 10:35:19

C# 3.0编译器

2013-06-05 10:11:20

索引器C#

2009-08-21 17:11:05

C#摄像头

2009-08-31 18:32:01

C# ListBoxE

2009-08-26 14:31:08

C#打印文件

2009-09-17 16:53:15

C#数组

2009-08-13 10:15:50

C#读取Excel

2009-09-07 15:27:04

C# MessageB

2009-08-19 15:38:59

C#代码

2009-08-19 10:09:21

C#和C++

2011-07-06 09:44:34

C#

2011-07-06 09:46:56

C#

2009-09-01 17:29:51

C#命名规约

2009-08-21 17:31:58

C#垃圾回收

2009-09-02 13:01:11

C#多路广播

2009-08-03 17:51:43

C#引用类型
点赞
收藏

51CTO技术栈公众号