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


个简单的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 { getset; } 
   
       
static Consoler() 
       { 
             Outputs 
= new Dictionary(); 
       } 
   
      
#region 输出操作 
   
       
//当前输出 
       public List Output { getprivate 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 { getset; } 
   
       
///  
       
/// 构造函数 
       
///  
       
/// 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]); 
        } 
   } 
}

posted @ 2008-06-02 14:39  guangrou  阅读(1586)  评论(4编辑  收藏  举报