在编译之前将代码插入C#方法

时间:2016-06-10 07:46:54

标签: c# .net reflection compilation roslyn

我有一些方法是从WinForms应用程序的入口点调用的。这些方法反过来呼唤其他人,有时甚至是彼此。

在每个方法的条目中,我插入了如下代码:

public static bool IsDebug
{
    #if (DEBUG)
        return (true);
    #else
        return (false);
    #endif
}

public void SomeMethod ()
{
    if (IsDebug) { Logger.WriteMethodTrace(MethodBase.GetCurrentMethod().Name); }
}

这种方法存在两个问题:

  • 每种方法都是手写的。
  • 它使用对于经常调用的方法来说太慢的反射。


REFLECTION :新的C#nameof(parameter)关键字可以很好地用于参数名称,但我还没有找到类似的方法名称构造。我想创建某种静态字典来保存TypeMethodInfo细节,但似乎无法在运行时提取方法名称而不用反射作为字典中的键。< / p>

用手书写:即使有一个避免反射的解决方案,每个方法都需要手工更改,这很乏味且容易出错。我想知道是否有一种方法可以在编译之前及时插入一行代码。不确定VS扩展或Roslyn会在这里提供帮助。理想情况下,如果可以自动插入,则应在不实际修改源代码的情况下进行插入。

请注意,分析堆栈跟踪不是一种选择。我一直走在那条路上,这是缓慢而不愉快的。

任何指针/建议都将不胜感激。

1 个答案:

答案 0 :(得分:4)

C#5.0有一个很好的功能。我想你尝试这个会很有用:

[Conditional("DEBUG")]
public void LogMethodNameInDebug(
    [CallerMemberName] string memberName = "",
    [CallerFilePath] string sourceFilePath = "", 
    [CallerLineNumber] int sourceLineNumber = 0)
{
    Logger.WriteMethodTrace(memberName);
)


public void SomeMethod()
{
    LogMethodNameInDebug(); // don't fillin the methodnames yourself, the compiler will do.
}

[Conditional("DEBUG")]编译为Release版本时,[CallerMemberName]将排除该方法。寻找更多信息:MSDN - ConditionalAttribute

[CallerMemberName]将填充compiletime (它填写调用者的参数,因此不使用反射或堆栈分析)。有关 SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook]; SLComposeViewControllerCompletionHandler myBlock = ^(SLComposeViewControllerResult result){ if (result == SLComposeViewControllerResultCancelled) NSLog(@"Cancelled"); else NSLog(@"Done"); [controller dismissViewControllerAnimated:YES completion:Nil]; }; controller.completionHandler = myBlock; [controller setInitialText:@"blah blah"]; [self presentViewController:controller animated:YES completion:Nil]; 的更多信息:MSDN - CallerMemberNameAttribute