⼀个简单的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 { 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]);
  }
  }
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。