No, you cannot get an instance of the calling class. This information is not even at the level of IL. Constructor B , decompiled into ILDasm, looks like this:
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Размер кода: 9 (0x9) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ret } // end of method B::.ctor
It has no parameter declarations, so there are no hidden parameters.
What you can find out is which particular method is calling you without specifying an instance of the class. This is done like this:
[MethodImpl(MethodImplOptions.NoInlining)] public B() { MethodBase callingMethod = new StackFrame(1).GetMethod(); Console.WriteLine($"Called from type: {callingMethod.DeclaringType.FullName}, " + $"calling method name: {callingMethod.Name}"); }
My output is:
Called from type: Test.A, calling method name: MethodA
You create a stack frame starting at 1 above your current frame, and request a method. Having a reflection-method handle, you can get information from it.
Notice that I applied the MethodImplOptions.NoInlining attribute to disable embedding this method at the call point, otherwise the wrong trace information could get into the stack trace.
Another important point: the StackFrame request is a costly, expensive operation, so you should not apply this solution in the production code. If you want information about that. who called you, in the production code, you should trust this to the compiler and use the [CallerMemberName] attribute, available from .NET 4.5:
public B([CallerMemberName] string callerName = null, [CallerFilePath] string callerFile = null, [CallerLineNumber] int callerLineNumber = -1) { Console.WriteLine($"Called from method: {callerName}, " + $"located {callerFile}@{callerLineNumber}"); }
Displays:
Called from method: MethodA, located D:\full path here\Test\Program.cs@42