【问题标题】:scripting with C#? [closed]用 C# 编写脚本? [关闭]
【发布时间】:2011-08-27 20:02:03
【问题描述】:

我广泛使用 Python 来执行各种临时数据处理和辅助任务。由于我正在学习 C#,我想看看我是否可以用 C# 重写其中的一些脚本会很有趣。

是否有可用的可执行文件获取 .cs 文件并在 ala python 中运行它?

【问题讨论】:

标签: c# scripting data-munging


【解决方案1】:

你可以这样做(创建一个控制台应用程序,代码与此类似)

...
using System.Reflection;
using System.CodeDom.Compiler;
...

namespace YourNameSpace
{
  public interface IRunner
  {
    void Run();
  }

  public class Program
  {
    static Main(string[] args)
    {
      if(args.Length == 1)
      {
        Assembly compiledScript = CompileCode(args[0]);
        if(compiledScript != null)
          RunScript(compiledScript);
      }
    }

    private Assembly CompileCode(string code)
    {
      Microsoft.CSharp.CSharpCodeProvider csProvider = new 
Microsoft.CSharp.CSharpCodeProvider();

      CompilerParameters options = new CompilerParameters();
      options.GenerateExecutable = false;
      options.GenerateInMemory = true;

      // Add the namespaces needed for your code
      options.ReferencedAssemblies.Add("System");
      options.ReferencedAssemblies.Add("System.IO");
      options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

      // Compile the code
      CompilerResults result;
      result = csProvider.CompileAssemblyFromSource(options, code);

      if (result.Errors.HasErrors)
      {
        // TODO: Output the errors
        return null;
      }

      if (result.Errors.HasWarnings)
      {
        // TODO: output warnings
      }

      return result.CompiledAssembly;
    }

    private void RunScript(Assembly script)
    {
      foreach (Type type in script.GetExportedTypes())
      {
        foreach (Type iface in type.GetInterfaces())
        {
          if (iface == typeof(YourNameSpace.Runner))
          {
            ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes);
              if (constructor != null && constructor.IsPublic)
              {
                YourNameSpace.IRunner scriptObject = constructor.Invoke(null) as 
YourNameSpace.IRunner;

                if (scriptObject != null)
                {
                  scriptObject.Run();
                }
                else
                {
                  // TODO: Unable to create the object
                }
              }
              else
              {
                // TODO: Not implementing IRunner
              }
            }
          }
        }
      }
  }
}

创建此控制台应用程序后,您可以在命令提示符下这样启动:

YourPath:\> YourAppName.exe "public class Test : IRunnder { public void Run() { 
Console.WriteLine("woot"); } }"

您可以轻松地将 Main 方法更改为接受文件而不是内联代码,因此您的控制台应用程序将具有与 python 或 ruby​​ 解释器类似的行为。只需将文件名传递给您的应用程序,然后在主函数中使用 StreamReader 读取它,然后将内容传递给 CompileCode 方法。像这样的:

static void Main(string[] args)
{
  if(args.Length == 1 && File.Exists(args[0]))
  {
    var assambly = CompileCode(File.ReadAllText(args[0]));
    ...
  }  
}

在命令行上:

YourPath:\> YourApp.exe c:\script.cs

你必须实现IRunner接口,你也可以简单地调用一个硬编码的Start方法而不继承接口,这只是为了展示动态编译和执行类的概念。

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    CS-Script:C# 脚本引擎

    http://www.csscript.net/

    【讨论】:

      【解决方案3】:

      将 C# 作为脚本运行的最新和最佳方法是利用 Roslyn。哪个是用 C# 编写的 C# 编译器。

      Glenn Block、Justin Rusbatch 和 Filip Wojcieszyn 已将 Roslyn 打包成一个名为 scriptcs 的程序,它完全可以满足您的需求。

      您可以在此处找到该项目。 http://scriptcs.net/

      你可以通过调用来运行一个名为server.csx的C#脚本文件

      scriptcs server.csx
      

      【讨论】:

        猜你喜欢
        • 2011-03-03
        • 2013-10-07
        • 2014-02-11
        • 1970-01-01
        • 1970-01-01
        • 2010-12-30
        • 1970-01-01
        • 2016-08-04
        • 2011-01-11
        相关资源
        最近更新 更多