Hello CodeDOM -- building C# and F# code from F#
A five-finger exercise in CodeDOM using the "Hello World" example from F# -- more interesting stuff to follow later:
module ProofOfConcept | |
open System.CodeDom | |
open System.CodeDom.Compiler | |
open System.IO | |
open Microsoft.CSharp | |
open Microsoft.FSharp.Compiler.CodeDom | |
let GenerateCode(compileunit: CodeCompileUnit) (provider:CodeDomProvider) = | |
// Build the output file name. | |
let sourceFile = Path.ChangeExtension("HelloWorld.", provider.FileExtension) | |
// Create a TextWriter to a StreamWriter to the output file. | |
use sw = new StreamWriter(sourceFile, false) | |
let tw = new IndentedTextWriter(sw, " ") | |
// Generate source code using the code provider. | |
provider.GenerateCodeFromCompileUnit(compileunit, tw, | |
new CodeGeneratorOptions()) | |
tw.Close() | |
sourceFile | |
let GenerateCSharpCode(compileunit: CodeCompileUnit) = | |
// Generate the code with the C# code provider. | |
let provider = new CSharpCodeProvider(); | |
GenerateCode compileunit provider | |
let GenerateFSharpCode(compileunit: CodeCompileUnit) = | |
// Generate the code with the F# code provider. | |
let provider = new FSharpCodeProvider(); | |
GenerateCode compileunit provider | |
[<EntryPoint>] | |
let main a = | |
let compileUnit = new CodeCompileUnit() | |
let samples = new CodeNamespace("Samples") | |
samples.Imports.Add(new CodeNamespaceImport("System")) | |
compileUnit.Namespaces.Add( samples ) |> ignore | |
let class1 = new CodeTypeDeclaration("Class1") | |
samples.Types.Add(class1) |> ignore | |
let start = new CodeEntryPointMethod(); | |
let cs1 = new CodeMethodInvokeExpression( | |
new CodeTypeReferenceExpression("System.Console"), | |
"WriteLine", new CodePrimitiveExpression("Hello CodeDOM World!")) | |
start.Statements.Add(cs1) |> ignore | |
class1.Members.Add( start ) |> ignore | |
GenerateCSharpCode compileUnit |> ignore | |
GenerateFSharpCode compileUnit |> ignore | |
0 |
which yields up
//------------------------------------------------------------------------------ | |
// <auto-generated> | |
// This code was generated by a tool. | |
// Runtime Version:2.0.50727.4211 | |
// | |
// Changes to this file may cause incorrect behavior and will be lost if | |
// the code is regenerated. | |
// </auto-generated> | |
//------------------------------------------------------------------------------ | |
namespace Samples { | |
using System; | |
public class Class1 { | |
public static void Main() { | |
System.Console.WriteLine("Hello CodeDOM World!"); | |
} | |
} | |
} |
which isn't StyleCop compliant, but is otherwise well formatted; and
//------------------------------------------------------------------------------ | |
// <autogenerated> | |
// This code was generated by a tool. | |
// Runtime Version: 2.0.50727.4211 | |
// | |
// Changes to this file may cause incorrect behavior and will be lost if | |
// the code is regenerated. | |
// </autogenerated> | |
//------------------------------------------------------------------------------ | |
namespace global | |
namespace Samples | |
// 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 | |
open System | |
exception ReturnException2ea1f686ef3e4730bedf29e248ff4aab of obj | |
exception ReturnNoneException2ea1f686ef3e4730bedf29e248ff4aab | |
[<AutoOpen>] | |
module FuncConvertFinalOverload2ea1f686ef3e4730bedf29e248ff4aab = | |
// 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 | |
Class1 = class | |
new() as this = | |
{ | |
} | |
static member UnnamedMethod_0 () = | |
System.Console.WriteLine("Hello CodeDOM World!") |> ignore | |
end | |
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | |
module __EntryPoint = | |
[<EntryPoint>] | |
let Main (args:string[]) = | |
Class1.UnnamedMethod_0() | |
0 |
which is a little idiosyncratic; the GUID-named types seem to be there in case of need from some construct that is not actually used in this simple example.
Now it just comes down to assembling to code object graph for something practical.
No comments :
Post a Comment