一个简单的C#在线IDE示例

时间:2023-02-10 14:25:49


个简单的C#在线IDE主要解决两个问题:
                     一是如何将网页上文本框的代码编译并执行;
                     二是如何将程序运行结果在网页上输出.

  第一个问题不难, dotNET已经有现成的C#编译类CSharpCodeProvider(或是其它语言的),再使用CompilerParameters类做为编译参数,就可以很容易的实现.

  第二个问题, 举最简单情况, 就是将Console.Write方法输出的内容在网页上显示出来.这其实也很好办,只要在编译之前, 在输出语句做一个替换, 将输出的内容存到另一个地方.等运行结束后, 再从那个地方取出来就是了.

代码实现如下:

using  System; 
using  System.Collections.Generic; 
using  System.Linq; 
using  System.Text; 
   
namespace  VSOnline.Framework 

   
///   
   
///  自定义的输出类 
   
///   
    public   class  Consoler 
   { 
       
// 存储所有输出 
        public   static  Dictionary Outputs {  get set ; } 
   
       
static  Consoler() 
       { 
             Outputs 
=   new  Dictionary(); 
       } 
   
      
#region  输出操作 
   
       
// 当前输出 
        public  List Output {  get private   set ; } 
   
       
public  Consoler() 
        { 
           Output 
=   new  List(); 
      } 
   
       
public   void  Write( object  str) 
        { 
           Output.Add(str.ToString()); 
        } 
   
        
public   void  WriteLine( object  str) 
      { 
         Output.Add(str.ToString() 
+   " \n " ); 
        } 
 
      
#endregion  
   } 
}

 

using  System; 
using  System.Reflection; 
using  Microsoft.CSharp; 
using  System.CodeDom.Compiler; 
using  System.Collections.Generic; 
using  System.Linq; 
using  System.Web; 
   
namespace  VSOnline.Framework 

   
///   
   
///  代码执行类 
   
///   
   public   class  CodeRun 
  { 
        
///   
       
///  Framework版本,可选择v2.0, v3.0, v3.5 
       
///   
        private   string  CompilerVersion {  get set ; } 
   
       
///   
       
///  构造函数 
       
///   
       
///  Framework版本,可选择v2.0, v3.0, v3.5 
 
    
public  CodeRun( string  compilerVersion) 
   { 
       CompilerVersion 
=  compilerVersion; 
   } 
   
   
///   
   
///  构造函数,默认为3.5版本 
   
///   
    public  CodeRun() 
   { 
       CompilerVersion 
=   " v3.5 "
   } 
   
   
///   
   
///  动态编译并执行代码 
   
///   
   
///  代码 
   
///  返回输出内容 
    public  List Run( string  code,  string  id,  params   string [] assemblies) 
   { 
       Consoler.Outputs.Add(id, 
new  Consoler()); 
       CompilerParameters compilerParams 
=   new  CompilerParameters(); 
       
// 编译器选项设置 
       compilerParams.CompilerOptions  =   " /target:library /optimize "
       
// compilerParams.CompilerOptions += @" /lib:""C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\"""; 
       
// 编译时在内存输出 
      compilerParams.GenerateInMemory  =   true
         
// 生成调试信息 
         compilerParams.IncludeDebugInformation  =   false
       
// 添加相关的引用 
        foreach  ( string  assembly  in  assemblies) 
       { 
           compilerParams.ReferencedAssemblies.Add(assembly); 
       } 
       compilerParams.ReferencedAssemblies.Add(
" mscorlib.dll " ); 
       compilerParams.ReferencedAssemblies.Add(
" System.dll " ); 
       
if  ( this .CompilerVersion  ==   " v3.5 "
       { 
           compilerParams.ReferencedAssemblies.Add(
" System.Core.dll " ); 
       } 
   
       
string  path  =   ""
       
try  
       { 
           path 
=  HttpContext.Current.Server.MapPath( " /bin/ " ); 
       } 
         
catch  { } 
   
       compilerParams.ReferencedAssemblies.Add(path 
+   " VSOnline.Framework.dll " ); 
         CSharpCodeProvider compiler 
=   new  CSharpCodeProvider( new  Dictionary() { {  " CompilerVersion " , CompilerVersion } }); 
       
// 编译 
       code  =  code.Replace( " Console.WriteLine " string .Format( " VSOnline.Framework.Consoler.Outputs[\ " { 0 }\ " ].WriteLine " , id)); 
       code 
=  code.Replace( " Console.Write " string .Format( " VSOnline.Framework.Consoler.Outputs[\ " { 0 }\ " ].Write " , id)); 
       CompilerResults results 
=  compiler.CompileAssemblyFromSource(compilerParams, code); 
         
// 错误 
        if  (results.Errors.HasErrors) 
       { 
             
foreach  (CompilerError error  in  results.Errors) 
             { 
                  Consoler.Outputs[id].Output.Add(error.ErrorText 
+   " \n " ); 
             } 
            
return  ReturnOutput(id); 
        } 
         
// 创建程序集 
       Assembly asm  =  results.CompiledAssembly; 
         
// 获取编译后的类型 
          object  mainClass  =  asm.CreateInstance( " Program " ); 
       Type mainClassType 
=  mainClass.GetType(); 
       
// 输出结果 
       mainClassType.GetMethod( " Main " ).Invoke(mainClass,  null ); 
   
       
return  ReturnOutput(id); 
   } 
   
   
private  List ReturnOutput( string  id) 
   { 
         
string [] output  =   new   string [Consoler.Outputs[id].Output.Count]; 
         Consoler.Outputs[id].Output.CopyTo(output, 
0 ); 
         Consoler.Outputs.Remove(id); 
   
        
return  output.ToList(); 
   } 
 } 
}


测试代码:
using  VSOnline.Framework; 
using  Microsoft.VisualStudio.TestTools.UnitTesting; 
using  System.Collections.Generic; 
using  System; 
using  FastDev.Core; 
using  System.Linq; 
   
namespace  Test 

   [TestClass()] 
   
public   class  CodeRunTest 
   { 
       [TestMethod()] 
       
public   void  RunTest() 
       { 
           CodeRun target 
=   new  CodeRun(); 
   
              
// 注意:以下是一个多行的 string 
            string  code  =   @"  
                          using System; 
   
                          public class Program 
                          { 
                               public static void Main() 
                              { 
                                   for(int index = 1;index <= 3;index++) 
                                   { 
                                          Console.Write(index); 
                                   } 
                               } 
                           }  
" ;    //  多行 string结束

           List expected 
=   new  List() {  " 1 " " 2 " " 3 "  }; 
           List actual; 
             actual 
=  target.Run(code,  " 1 " ); 
           Assert.AreEqual(
true , expected.SerializeEqual(actual)); 
   
           actual 
=  target.Run(code,  " 2 " ); 
           Assert.AreEqual(
true , expected.SerializeEqual(actual)); 
       } 
   
       [TestMethod()] 
       
public   void  Run35Test() 
       { 
           CodeRun target 
=   new  CodeRun(); 
   
           
string  code  =   @"  
                  using System; 
                  using System.Collections; 
                  using System.Collections.Generic; 
                  using System.Linq; 
   
                  public class Program 
                  { 
                       public static string Name { get; set; } 
   
                        public static void Main() 
                        { 
                            Name = ""3""; 
                            Console.Write(Name); 
                        } 
                  } 
"
             List actual; 
             actual 
=  target.Run(code,  " 1 " " System.Core.dll " ); 
             Assert.AreEqual(
" 3 " , actual[ 0 ]); 
        } 
   } 
}