1

在我的应用程序中,我有一个小动作日志。在那里,我将某些方法的最后几次调用保存在我的应用程序中,如下所示:

saveLastAction(MethodBase.GetCurrentMethod(), getCurrentStatus(), item, /*loadFresh*/ false);

它允许我浏览和刷新我的最后一个动作

    public void Refresh(bool loadFresh = true)
    {
        if (!isInitialized) return;

        try
        {
            lastStatus = getCurrentStatus();

            var parameters = lastActionsParameters.Pop();
            var method = lastActions.Pop();

            //Set the load Fresh parameter to True
            parameters[method.GetParameters().First(pi => pi.Name == "loadFresh").Position] = loadFresh;

            //Invoke the Method again with the adopted parameters
            method.Invoke(this, parameters);

        }
        catch
        {
        }
    }

在我将调用 saveLastAction 的方法之一更改为异步之前,我工作得很好。从那时起MethodBase.GetCurrentMethod()只返回 MoveNext 函数,而不是我调用的实际函数。

有没有办法获得被调用函数的实际 MethodBase 对象,无论是在保存还是调用时都没有关系。

最好的问候 lolsharp

4

3 回答 3

2

我创建了一个小帮助功能:

private MethodInfo getMethodBase(object caller, [CallerMemberName]string methodName = "")
    {
        //Binding Flags to include private functions
        return caller.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
    }

直接使用 CallerMemberNameAttribute 不起作用,因为我也在使用 params 参数。最终采用了与 Peters 非常相似的方法。

于 2015-01-27T13:20:04.970 回答
0

你真的需要这个MethodBase对象吗?或者仅记录足够的细节以使人们能够弄清楚它是哪种方法就足够了?

如果是后者,那么它相当简单:请注意,正在执行的方法实际上包含在编译器生成的类中,其中类名本身包含编译器重写以生成该类的方法的名称。

因此,在您的saveLastAction()方法中,您可能会记录MethodBase.Name属性值,您应该首先检查该MethodBase.DeclaringType.Name值,如果它看起来像<SomeMethodName>d_5(右尖括号后的细节也可能有所不同),您可以使用尖括号内的文本方法名称而不是MethodBase.Name属性值。

请注意,仅允许编译器生成带有尖括号的类名,因此您不必担心会误报。

作为额外的奖励,这将允许您的日志记录代码也可以使用迭代器方法。:)

如果您需要MethodBase对象本身,那会更复杂一些,但会遵循相同的基本策略。MethodBase.DeclaringType.DeclaringType获取方法名称,然后在类型(即包含编译器生成的类型的类型)中查找该方法。请注意,如果该方法有多个重载,则识别所使用的特定重载可能会很棘手或不切实际。

于 2015-01-20T08:52:43.160 回答
0

这将在C#7 中使用本地函数变得容易得多:

public Task DoAThingAsync()
{
    var method = MethodBase.GetCurrentMethod();
    LogMethod(method);

    return doWork();

    // Define inner function to actually do the work
    async Task doWork()
    {
         // Do the work here
    }
}

您已经可以使用匿名方法或委托来实现这一点,但这使得代码非常清晰。

于 2017-01-27T12:59:06.933 回答