C#Console を作ってみた

Groovy を勉強している時に、GroovyConsole で色々試してるんだけど、C# でも似たようなの欲しいなと思って WPF の勉強がてらに作ってみた。

xaml ファイル


  
    
      
      
    
    
      

cs ファイル

using System;
using System.Windows;
using System.Windows.Input;
using System.IO;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;

namespace CSharpConsole
{
  /// 
  /// ConsoleView.xaml の相互作用ロジック
  /// 
  public partial class ConsoleView : Window
  {
    public static readonly ICommand RunCommand = new RoutedCommand("RunCommand", typeof(ConsoleView));   

    private MemoryStream stream;
    private StreamWriter writer;
    private StreamReader reader;
    private string classTemplate = @"using System;
using System.Collections.Generic;
using System.Text;
public class Test {{
  public static void Method() {{
  {0}
  }}
}}";
    public ConsoleView()
    {
      InitializeComponent();

      stream = new MemoryStream();
      writer = new StreamWriter(stream);
      writer.AutoFlush = true;
      reader = new StreamReader(stream);
      Console.SetOut(writer);

      this.txtSource.Focus();

      var runCommandBinding = new CommandBinding(RunCommand, RunCommand_Executed);   
      this.CommandBindings.Add(runCommandBinding);   

      KeyBinding SaveKeyBinding = new KeyBinding(
        RunCommand,
        Key.R,
        ModifierKeys.Control);
      this.InputBindings.Add(SaveKeyBinding);
    }

    private void RunCommand_Executed(object source, ExecutedRoutedEventArgs e)   
    {
      long position = stream.Position;
      try
      {
        string src = string.Format(classTemplate, this.txtSource.Text);
        CSharpCodeProvider provider = new CSharpCodeProvider();

        CompilerParameters param = new CompilerParameters();
        param.GenerateInMemory = true;

        CompilerResults result = provider.CompileAssemblyFromSource(param, src);
        if (result.Errors.HasErrors)
        {
          Console.WriteLine(src);
          foreach (CompilerError error in result.Errors)
          {
            Console.WriteLine(error);
          }
          return;
        }

        Assembly asm = result.CompiledAssembly;

        Type type = asm.GetType("Test");

        MethodInfo method = type.GetMethod("Method");
        method.Invoke(null, null);
      }
      finally
      {
        stream.Position = position;

        this.txtConsole.Text = string.Format("{0}{1}{2}", this.txtConsole.Text, Environment.NewLine, reader.ReadToEnd());
      }
    }  
  }
}

Stream とか使いっぱなしなのは、アプリケーション終了したら勝手に閉じられるでしょ!って考え方で手抜き。
んで、実行結果がこれ

ちょっとした確認とかで、使うと便利かな〜と。
PowerShell とか IronPython でも確認出来るんだけど、未だ使いこなせてなくて…。