MethodBase异步函数的对象

时间:2015-01-19 10:44:51

标签: c# asynchronous reflection methodbase

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

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

3 个答案:

答案 0 :(得分: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的做法非常相似。

答案 1 :(得分:0)

你真的需要MethodBase对象吗?或者仅仅记录足够的细节,人类可以找出它是哪种方法就足够了?

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

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

请注意,只允许编译器使用这些尖括号生成类名,因此您不必担心会出现误报。

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

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

答案 2 :(得分:0)

C#7 using local functions中,这将变得更容易:

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
    }
}

您已经可以使用匿名方法或委托实现此目的,但这使代码非常清晰。