调用私有方法保留调用堆栈

Edw*_*win 14 c# reflection methods private

我正试图找到"打破非公开方法"的解决方案.

我只是想调用RuntimeMethodInfo.InternalGetCurrentMethod(...),传递我自己的参数(所以我可以实现GetCallingMethod()),或直接RuntimeMethodInfo.InternatGetCurrentMethod(ref StackCrawlMark.LookForMyCaller)在我的日志记录例程中使用.GetCurrentMethod实施方式如下:

[MethodImpl(MethodImplOptions.NoInlining)] 
public static MethodBase GetCurrentMethod() 
{     
    StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;     
    return RuntimeMethodInfo.InternalGetCurrentMethod(ref lookForMyCaller); 
}
Run Code Online (Sandbox Code Playgroud)

InternalGetCurrentMethod声明在哪里:内部:-).

我使用反射调用方法没有问题,但这会弄乱调用堆栈,这只是必须要保留的一件事,否则它会破坏它的目的.

我的堆栈跟踪保持接近原始的几率是多少(至少在允许的StackCrawlMarks 的距离内,这是LookForMe,LookForMyCallerLookForMyCallersCaller.是否有一些复杂的方法来实现我想要的?

Meh*_*dad 20

如果我喜欢C#,那就是动态方法.

它们让您绕过.NET创建者的每个目标和意图.:d

这是一个(线程安全的)解决方案:

(Eric Lippert,请不要读这个......)

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 8 年后,这仍然派上用场。我用它从基类构造函数中获取调用派生类构造函数的自定义属性。当然,我可以用更传统的方式解决它(并且一直到我发现这个),但这非常符合要求! (2认同)