【问题标题】:MethodBase Object of async function异步函数的 MethodBase 对象
【发布时间】:2015-01-19 10:44:50
【问题描述】:

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

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 对象,无论是保存时还是调用时都无所谓。

最好的问候 大声笑

【问题讨论】:

  • 您提供的信息不够。

标签: c# asynchronous reflection methodbase


【解决方案1】:

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

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 的方法。

【讨论】:

  • 我试图找到一个替代者作为提问者,这非常有效。谢谢!
【解决方案2】:

你真的需要MethodBase 对象吗?还是只记录足够的细节以供人类判断是哪种方法就足够了?

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-28
      • 2011-10-14
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多