3

Assume I have a simple script writing in C# 9 like this:

using System;
using System.IO;

// What to put in the ???
var exeFolder = Path.GetDirectoryName(typeof(???).Assembly.Location);

Before, with the full program, we can use the Main class as an "indicator" class. this and this.GetType() is not available because technically it's inside a static method. How do I get it now?


A workaround I thought of while typing the question is Assembly.GetCallingAssembly():

var exeFolder = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);

It works for my case, but I can only get the Assembly, not the TypeInfo that in which the code is running.

Luke Vo
  • 17,859
  • 21
  • 105
  • 181
  • 2
    May be try to do it via executing method: `MethodInfo.GetCurrentMethod().DeclaringType` – Dmitry Bychenko Dec 06 '20 at 02:50
  • You may look at [Cannot find Main method using reflection with .NET 5 top level calls](https://stackoverflow.com/questions/64966831/cannot-find-main-method-using-reflection-with-net-5-top-level-calls), seems to be a dupe candidate – Pavel Anikhouski Dec 06 '20 at 12:22

3 Answers3

6

You can also get the assembly using GetEntryAssembly.

Once you have the assembly that your code is in, you can get its EntryPoint, which is the compiler-generated "Main" method. You can then do DeclaringType to get the Type:

Console.WriteLine(Assembly.GetEntryAssembly().EntryPoint.DeclaringType);

The above should get the compiler-generated "Program" class even if you are not at the top level.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Dang I feel super bad that I cannot mark both answers as correct. I would mark the other as it is "nearer" to my question, but your answer is still so good. Thank you, I learnt something new today. – Luke Vo Dec 06 '20 at 13:22
5

For C# 10 (See 4th point in the breaking changes) compiler generates Program class for top-level statements so you can use it:

Console.WriteLine(typeof(Program).FullName);

And though original (C# 9) docs state that:

Note that the names "Program" and "Main" are used only for illustrations purposes, actual names used by compiler are implementation dependent and neither the type, nor the method can be referenced by name from source code.

ASP.NET Core integration testing docs rely on this naming convention for the class.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
3

I suggest starting from the method which is executing (Main):

TypeInfo result = MethodBase
  .GetCurrentMethod() // Executing method         (e.g. Main)
  .DeclaringType      // Type where it's declared (e.g. Program)
  .GetTypeInfo();    

If you want Type, not TypeInfo drop the last method:

Type result = MethodBase
  .GetCurrentMethod() // Executing method         (e.g. Main)
  .DeclaringType;     // Type where it's declared (e.g. Program)

 
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215