Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scripting with C#? [closed]

I have used Python extensively for doing various adhoc data munging and ancillary tasks. Since I am learning C#, I figure it would be fun to see if I can rewrite some of these scripts in C#.

Is there an executable available that takes a .cs file and runs it ala python?

like image 924
voidstar Avatar asked May 18 '11 07:05

voidstar


2 Answers

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.

like image 188
Dominic St-Pierre Avatar answered Sep 23 '22 05:09

Dominic St-Pierre


CS-Script: The C# Script Engine

http://www.csscript.net/

like image 28
Jonathan Allen Avatar answered Sep 24 '22 05:09

Jonathan Allen