F# プロジェクト内では C# のコードが利用できないので C# から F# に変換できたら良いですね。 F# PowerPack には CodeDOM の実装があるのでこれを使えば良さそうです。
CodeDOM を使って C# のコードを F# に変換するためにはまず C# のコードを CodeCompileUnit
に落とし込む必要があります。 CodeCompileUnit
形式のオブジェクトは次のように F# のコードに変換できます。
let fsharpCode compileUnit = use provider = new FSharpCodeProvider () let options = CodeGeneratorOptions (IndentString = " ") let builder = StringBuilder () use writer = new StringWriter (builder) provider.GenerateCodeFromCompileUnit (compileUnit, writer, options) builder.ToString ()
インデントが 3 スペースなのは完全に趣味です。
C# のコードを CodeCompileUnit
にするには CSharpCodeProvider.Parse
メソッドを使えば良いように見えますが, NotImplementedException
が投げられます。そこで NRefactory を用います。
let compileUnit csharpSourcePath = let compilation = let projectContent = CSharpProjectContent () SimpleCompilation (projectContent) let syntaxTree = let parser = CSharpParser () use reader = new StreamReader (csharpSourcePath) parser.Parse (reader) let visitor = CodeDomConvertVisitor () visitor.Convert (compilation, syntaxTree, null)
例えば次の C# コードを変換します。
using System; class Program { static void Main() { Console.WriteLine("Hello, World!"); } }
結果は次のようになります。
//------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version: 4.0.30319.17929 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace global namespace global // Generated by F# CodeDom #nowarn "49" // uppercase argument names #nowarn "67" // this type test or downcast will always hold #nowarn "66" // this upcast is unnecessary - the types are identical #nowarn "58" // possible incorrect indentation.. #nowarn "57" // do not use create_DelegateEvent #nowarn "51" // address-of operator can occur in the code #nowarn "1183" // unused 'this' reference exception ReturnException3b9ed1539eac46fc9190777a400ea3c7 of obj exception ReturnNoneException3b9ed1539eac46fc9190777a400ea3c7 [<AutoOpen>] module FuncConvertFinalOverload3b9ed1539eac46fc9190777a400ea3c7 = // This extension member adds to the FuncConvert type and is the last resort member in the method overloading rules. type global.Microsoft.FSharp.Core.FuncConvert with /// A utility function to convert function values from tupled to curried form static member FuncFromTupled (f:'T -> 'Res) = f type Program = class new() as this = { } static member Main () = Console.WriteLine("Hello, World!") |> ignore end
System
名前空間が open
されていなかったり, Main
メソッドが EntryPoint
でなかったりして,残念ながら完全とはいえません。しかし,一から書き直すよりは大分負担が少ないのではないでしょうか。