I am trying to find a solution to 'break into non-public methods'.
I just want to call RuntimeMethodInfo.InternalGetCurrentMethod(...)
, passing my own parameter (so I can implement GetCallingMethod()
), or directly use RuntimeMethodInfo.InternatGetCurrentMethod(ref StackCrawlMark.LookForMyCaller)
in my logging routines. GetCurrentMethod
is implemented as:
[MethodImpl(MethodImplOptions.NoInlining)]
public static MethodBase GetCurrentMethod()
{
StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
return RuntimeMethodInfo.InternalGetCurrentMethod(ref lookForMyCaller);
}
where InternalGetCurrentMethod
is declared: internal :-).
I have no problem calling the method using reflection, but this messes up the call stack and that is just the one thing that has to be preserved, otherwise it defeats its purpose.
What are my odds of keeping the stacktrace close to the original (at least within the distance of the allowed StackCrawlMark
s, which are LookForMe
, LookForMyCaller
and LookForMyCallersCaller
. Is there some complex way to achieve what I want?
An object user can use the public methods, but can't directly access private instance variables. You can make methods private too. Object users can't use private methods directly. The main reason to do this is to have internal methods that make a job easier.
Private methods are useful for breaking tasks up into smaller parts, or for preventing duplication of code which is needed often by other methods in a class, but should not be called outside of that class.
class ClassOne { private: void methodOne(); public: void methodTwo(); }; So I should be able to access methodOne through methodTwo but without writing { methodTwo();} beside methodOne. Help me please? If you want one method to call the other, just do so.
Private methods are typically used when several methods need to do the exact same work as part of their responsibility (like notifying external observers that the object has changed), or when a method is split in smaller steps for readability.
If there's one thing I love about C#, it's dynamic methods.
They let you bypass every goal and intention of the .NET creators. :D
Here's a (thread-safe) solution:
(Eric Lippert, please don't read this...)
enum MyStackCrawlMark { LookForMe, LookForMyCaller, LookForMyCallersCaller, LookForThread }
delegate MethodBase MyGetCurrentMethodDelegate(ref MyStackCrawlMark mark);
static MyGetCurrentMethodDelegate dynamicMethod = null;
static MethodBase MyGetCurrentMethod(ref MyStackCrawlMark mark)
{
if (dynamicMethod == null)
{
var m = new DynamicMethod("GetCurrentMethod",
typeof(MethodBase),
new Type[] { typeof(MyStackCrawlMark).MakeByRefType() },
true //Ignore all privilege checks :D
);
var gen = m.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0); //NO type checking here!
gen.Emit(OpCodes.Call,
Type.GetType("System.Reflection.RuntimeMethodInfo", true)
.GetMethod("InternalGetCurrentMethod",
BindingFlags.Static | BindingFlags.NonPublic));
gen.Emit(OpCodes.Ret);
Interlocked.CompareExchange(ref dynamicMethod,
(MyGetCurrentMethodDelegate)m.CreateDelegate(
typeof(MyGetCurrentMethodDelegate)), null);
}
return dynamicMethod(ref mark);
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void Test()
{
var mark = MyStackCrawlMark.LookForMe; //"Me" is Test's _caller_, NOT Test
var method = MyGetCurrentMethod(ref mark);
Console.WriteLine(method.Name);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With