Как изменить точку входа консольного приложения ac #? - PullRequest
0 голосов
/ 14 октября 2018

Мне интересно, возможно ли изменить точку входа консольного приложения .NET с Main на Main2 метод в приведенном ниже примере:

class Program
{ 
    static void Main(string[] args)
    {
        Console.WriteLine("Main");
    }

    //desired entry point
    static void Main2(string[] args)
    {
        Console.WriteLine("Main2");
    }
}

Я исследовал код IL этих двух,Вот метод Main:

  .method private hidebysig static void 
    Main(
      string[] args
    ) cil managed 
  {
    .entrypoint
    .maxstack 8

    // other instructions

  } // end of method Program::Main

И метод Main2:

.method private hidebysig static void 
    Main2(
      string[] args
    ) cil managed 
  {
    .maxstack 8

    //other instructions
  } // end of method Program::Main2

Единственное отличие - это прецедент инструкции .entrypoint в методе Main,который, насколько я понимаю, обнаруживается CLR при запуске приложения.

Есть ли способ повлиять на csc, чтобы пометить другой метод с помощью этой инструкции?Могут ли другие компиляторы добиться цели?

РЕДАКТИРОВАТЬ Мой вопрос отличается от этого , потому что я спрашиваю о csc поведении компилятора (и других компиляторов) ... в частности, как поставить.entrypoint инструкция в другом месте

Ответы [ 4 ]

0 голосов
/ 18 октября 2018

Этого можно добиться с помощью AssemblyBuilder и других вещей из библиотеки System.Reflection.

        AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.Save);

        TypeBuilder typeBuilder = assemblyBuilder
            .DefineDynamicModule("Module", "Test.exe", false)
            .DefineType("Program", TypeAttributes.Public);

        MethodBuilder methodBuilder = typeBuilder.DefineMethod("Main2", MethodAttributes.Public | MethodAttributes.Static);

        ILGenerator ilGenerator = methodBuilder.GetILGenerator();
        ilGenerator.EmitWriteLine("Main2");
        ilGenerator.Emit(OpCodes.Ret);

        assemblyBuilder.SetEntryPoint(methodBuilder);

        typeBuilder.CreateType();
        assemblyBuilder.Save("Test.exe");

Это дает следующий код IL (.entryPoint помещается в метод Main2):

    .method public static 
       void Main2 () cil managed 
   {
       // Method begins at RVA 0x2050
       // Code size 11 (0xb)
       .maxstack 1
       .entrypoint

        IL_0000: ldstr "Main2"
        IL_0005: call void [mscorlib]System.Console::WriteLine(string)
        IL_000a: ret
   } // end of method Program::Main2

Если вы выполните Test.exe, вы увидите, чтоMain2 метод выполняется

0 голосов
/ 14 октября 2018

Это невозможно, по определению Main является точкой входа приложения C #.

Основной метод - это точка входа приложения C #.(Для библиотек и служб не требуется метод Main в качестве точки входа.) При запуске приложения метод Main является первым вызванным методом.

Источник: MSDN

0 голосов
/ 14 октября 2018

Точка входа должна иметь имя Main, как указано в спецификации языка C # §3.1:

3.1 Запуск приложения

Запуск приложения происходит, когда среда выполнения вызывает определенный метод, который называется точкой входа приложения.Этот метод точки входа всегда называется Main и может иметь одну из следующих подписей:

static void Main() {...}
static void Main(string[] args) {...}
static int Main() {...}
static int Main(string[] args) {...}

См. Слова «всегда именуется Main»?Если вы изменили точку входа на что-то отличное от Main, написав другой компилятор, этот компилятор по определению не будет компилятором C #.:)

0 голосов
/ 14 октября 2018

Метод должен называться Main, но вы можете использовать опцию -main, чтобы указать, какой метод класса Main является точкой входа.

(использование Main в качестве точки входа является частью определения C # - в спецификации C # v5 оно содержится в §3.1, вы могли бы преодолеть это, но это было бы самостоятельно.)

...