Можно ли скомпилировать C# в IL и декомпилировать полученный IL в F #? - PullRequest
2 голосов
/ 20 февраля 2020

C# компилируется в IL, который затем легко декомпилируется обратно в C# с использованием ILSpy или dotPeek.

Существует ли какой-либо инструмент, позволяющий декомпилировать тот же IL в F #?

то есть есть хитрый способ перевести C# в F # через IL?

ОБОСНОВАНИЕ:

  • У нас очень большой C# проектировать и хотеть "go функционал".
  • Перевод - это огромная работа.
  • Если перевод с первого прохода может быть автоматизирован, мы можем улучшить его вручную после

то есть это было бы быстрее, чем писать все с нуля на F #.

Мы еще не разбираемся в F #, поэтому возможна наивность этого вопроса.

ДОПОЛНИТЕЛЬНОЕ ПРИМЕЧАНИЕ Да, мы мы используем функциональные возможности в C#, но по разным причинам мы хотим, чтобы go был полностью функциональным с F #. Этот выбор не подлежит обсуждению здесь, но спасибо за комментарии к этому.

Ответы [ 3 ]

8 голосов
/ 20 февраля 2020

Idiomati c F # код использует разные типы, подходы и структуру. От декомпиляции сгенерированного C# -генерированного IL до F # выиграть нечего, особенно если учесть, что вы можете легко взаимодействовать с кодом C#. Что еще хуже, декомпиляция чего-либо приводит к потере большого количества информации - имен местных жителей, констант, комментариев и т.д. Это не невозможно, но вы тратите много сил на восстановление чего-то, что в любом случае является промежуточным шагом.

Разбейте ваш код C# на части, которые вы можете медленно заменить кодом F #. Таким образом, у вас есть шанс создать хороший код F # и постепенно заменять все по мере необходимости. Не начинайте писать что-либо с нуля - сохраняйте как можно больше старого кода и изменяйте только то, что необходимо изменить, чтобы улучшить взаимодействие с кодом F #.

C# уже довольно «функционален» -capable "язык - не такой аккуратный и выразительный, как F #, но есть очень мало вещей, которые вы можете сделать в F #, но не в C# достаточно простым способом. Это означает, что постепенное переключение на функциональный стиль не так сложно, как может показаться - и это работа, которую вы не можете избежать в любом случае, если ваша цель (по какой-то причине; я надеюсь, что у вас есть реальная цель, и это просто промежуточный шаг :) функциональный код.

3 голосов
/ 20 февраля 2020

Как показано здесь, вы теряете ценную информацию при компиляции в 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")

Конечно, вывод для тривиальной программы. Потребовалось бы намного больше работы, чтобы поддержать разумное преобразование, но, возможно, преобразование не должно быть совершенным. Может быть, если он достанет вам эшафот, вы, вероятно, сможете заполнить его в идиоматизме c F #.

И, как всегда, в автоматизации:

enter image description here

0 голосов
/ 20 февраля 2020

Да, на самом деле Рослин имеет прямую поддержку для этого. нет необходимости компилировать и декомпилировать ...

...