在我的应用程序中,我有一个小的操作日志。在这里,我保存了应用程序中某些方法的最后几次调用,如下所示:
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致敬
发布于 2015-01-27 21:20:05
我创建了一个小的帮助函数:
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参数。最后,我们采用了与Peters非常相似的方法。
发布于 2015-01-20 16:52:43
您真的需要MethodBase对象吗?或者,仅仅记录足够的细节就足以让人知道是哪种方法了吗?
如果是后者,则相当简单:请注意,正在执行的方法实际上包含在编译器生成的类中,其中类名称本身包含编译器重写以生成该类的方法的名称。
因此,在您的saveLastAction()方法中,假设您记录了MethodBase.Name属性值,您应该首先检查MethodBase.DeclaringType.Name值,如果它看起来像<SomeMethodName>d_5 (右尖括号后的细节可能也会有所不同),则可以使用尖括号内的文本作为方法名称,而不是MethodBase.Name属性值。
请注意,只有编译器才能生成带有这些尖括号的类名,因此您不必担心会出现误报。
作为一个额外的好处,这将允许您的日志代码与迭代器方法一起工作。:)
如果需要MethodBase对象本身,就会稍微复杂一些,但遵循相同的基本策略。获取方法名,然后在MethodBase.DeclaringType.DeclaringType类型(即包含编译器生成的类型的类型)中查找该方法。请注意,如果该方法有多个重载,则识别所使用的特定重载可能很棘手或不切实际。
发布于 2017-01-27 20:59:07
在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
}
}您已经可以通过匿名方法或委托来实现这一点,但这使得代码非常清晰。
https://stackoverflow.com/questions/28022799
复制相似问题