用 C# 编写脚本?

发布于 2024-11-08 03:36:06 字数 1539 浏览 0 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

乖乖 2024-11-15 03:36:06

您可以执行类似的操作(使用与此类似的代码创建一个控制台应用程序)

...
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 方法而不继承该接口,这只是为了展示动态编译类并执行的概念它。

希望有帮助。

You can do something like this (Create a Console app with code similar to this one)

...
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
              }
            }
          }
        }
      }
  }
}

After creating this console app you can start this like this at a command prompt:

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

You can easily change the Main method to accept file instead of inline code, so your console app would have a simillar behaviour as the python or ruby interpreter. Simply pass a filename to your application and read it with a StreamReader in the main function and pass the content to the CompileCode method. Something like this:

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

And on the command line:

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

You have to implement the IRunner interface, you could as well simply call a hard-coded Start method without inheriting the interface, that was just to show the concept of compiling class on the fly and executing it.

Hope it help.

明月夜 2024-11-15 03:36:06

CS-Script:C# 脚本引擎

http://www.csscript.net/

CS-Script: The C# Script Engine

http://www.csscript.net/

雨夜星沙 2024-11-15 03:36:06

将 C# 作为脚本运行的最新且最好的方法是利用 Roslyn。这是用 C# 编写的 C# 编译器。

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

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

您可以运行名为 server.csx 的 C# 脚本文件通过致电

scriptcs server.csx

The latest and best way to run C# as a script is to leverage Roslyn. Which is C# compiler written in C#.

Glenn Block, Justin Rusbatch and Filip Wojcieszyn have packaged up Roslyn into a program, called scriptcs, that does exactly what you want.

You can find the project here. http://scriptcs.net/

You can run a C# script file called server.csx by calling

scriptcs server.csx
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文