正如这里所反映的,当您编译为 IL 时,您会丢失宝贵的信息。阅读 C# 代码来翻译所有高级信息更为可行。
刚刚拼凑了一个SyntaxWalker。
public class FsVisitor : CSharpSyntaxWalker
{
public override void VisitUsingDirective(UsingDirectiveSyntax node)
{
PrintLn("open {0}", node.Name);
}
public override void VisitClassDeclaration(ClassDeclarationSyntax node)
{
PrintLn("type {0} =", node.Identifier);
Enter();
base.VisitClassDeclaration(node);
Exit();
}
public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
{
var isStatic = node.Modifiers.Any(t => t.ValueText == "static");
var modifiers = String.Join(" ", node.Modifiers);
PrintLn("{0}{1} ({2}) = ",
isStatic ? $"{modifiers} member " : $"member {modifiers} this.",
node.Identifier,
String.Join(", ", node.ParameterList.Parameters.Select(p => $"{p.Identifier} : {p.Type}")));
Enter();
base.VisitMethodDeclaration(node);
Exit();
}
public override void VisitInvocationExpression(InvocationExpressionSyntax node)
{
PrintLn("{0}", node);
base.VisitInvocationExpression(node);
}
private StringBuilder builder = new StringBuilder();
private int intendLevel = 0;
void Enter() => intendLevel++;
void Exit() => intendLevel--;
void Print(string format, params object[] args)
{
if (format == null) return;
builder.Append('\t', intendLevel);
builder.AppendFormat(format, args);
}
void PrintLn(string format = default, params object[] args)
{
Print(format, args);
builder.AppendLine();
}
public override string ToString() => builder.ToString();
}
我用一个简单的 C# 程序试了一下:
var code =
@"
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello World"");
Console.ReadKey();
}
private void SayHello()
{
Console.WriteLine(""Hello"");
}
}";
var visitor = new FsVisitor();
visitor.Visit(CSharpSyntaxTree.ParseText(code).GetCompilationUnitRoot());
Console.WriteLine(visitor.ToString());
输出:
open System
type Program =
static member Main (args : string[]) =
Console.WriteLine("Hello World")
Console.ReadKey()
member private this.SayHello () =
Console.WriteLine("Hello")
当然,输出是一个简单的程序。
支持合理的转换需要更多的工作,但也许转换不一定是完美的。也许如果它为您提供了脚手架,您可能可以用惯用的 F# 自己填充它。
在自动化方面一如既往: