Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在编译之前将代码插入C#方法_C#_.net_Reflection_Compilation_Roslyn - Fatal编程技术网

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

在编译之前将代码插入C#方法,c#,.net,reflection,compilation,roslyn,C#,.net,Reflection,Compilation,Roslyn,我有几个方法是从WinForms应用程序的入口点调用的。这些方法依次调用其他方法,有时也相互调用 在每个方法的输入处,我插入了如下代码: public static bool IsDebug { #if (DEBUG) return (true); #else return (false); #endif } public void SomeMethod () { if (IsDebug) { Logger.WriteMethod

我有几个方法是从WinForms应用程序的入口点调用的。这些方法依次调用其他方法,有时也相互调用

在每个方法的输入处,我插入了如下代码:

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

public void SomeMethod ()
{
    if (IsDebug) { Logger.WriteMethodTrace(MethodBase.GetCurrentMethod().Name); }
}
这种方法有两个问题:

  • 每种方法都是手写的
  • 它使用的反射对于频繁调用的方法来说太慢
.
反射:新的C#
nameof(parameter)
关键字对参数名很有效,但我还没有找到类似的方法名构造。我曾考虑过创建某种静态字典来保存
Type
MethodInfo
的详细信息,但似乎无法在运行时提取方法名,而不将反射用作字典中的键

手工编写:即使有避免反射的解决方案,每个方法都需要手工修改,这既繁琐又容易出错。我想知道是否有办法在编译之前及时插入一行代码。不确定是VS分机还是Roslyn会帮上忙。理想情况下,如果可以自动插入,则插入应该在不实际修改源代码的情况下进行

请注意,分析堆栈跟踪不是一个选项。我一直沿着那条路走,路很慢,很不舒服

如果您有任何建议,我们将不胜感激。

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”)]
将该方法编译为发布版本时排除。查看更多信息:

并且
[CallerMemberName]
将在compiletime中填充(它填充调用者上的参数,因此不使用反射或堆栈分析)。有关
[CallerMemberName]
的更多信息,请点击此处:

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”)]
将该方法编译为发布版本时排除。查看更多信息:


并且
[CallerMemberName]
将在compiletime中填充(它填充调用者上的参数,因此不使用反射或堆栈分析)。有关
[CallerMemberName]
的更多信息,请点击此处:

您可以使用AOP(面向方面编程)范例。C#world最著名的代表人物是PostSharp。它的免费版本可以做你想做的事。为什么不简单地使用TraceListener并在app.config中根据需要打开或关闭它呢?@Evk:尽管这个问题已经得到了回答,但PostSharp似乎是一个值得探索的好建议。谢谢@RaheelKhan认为,在当前的方法中,不能在运行时刷新日志记录级别(实际上,甚至无法通过配置进行切换)——必须重新编译代码才能做到这一点。通常,您希望在已经运行的应用程序上启用调试级日志记录。@Evk:您说得对。然而,在发布问题时,我倾向于缩小上下文和代码的范围,以获得一个简洁的问题。这里的上下文不是关于如何使用最佳实践进行日志记录。公认的答案对于我的目的来说足够灵活(不包括自动化)。您可以使用AOP(面向方面编程)范式。C#world最著名的代表人物是PostSharp。它的免费版本可以做你想做的事。为什么不简单地使用TraceListener并在app.config中根据需要打开或关闭它呢?@Evk:尽管这个问题已经得到了回答,但PostSharp似乎是一个值得探索的好建议。谢谢@RaheelKhan认为,在当前的方法中,不能在运行时刷新日志记录级别(实际上,甚至无法通过配置进行切换)——必须重新编译代码才能做到这一点。通常,您希望在已经运行的应用程序上启用调试级日志记录。@Evk:您说得对。然而,在发布问题时,我倾向于缩小上下文和代码的范围,以获得一个简洁的问题。这里的上下文不是关于如何使用最佳实践进行日志记录。被接受的答案对我来说足够灵活(不包括自动化)。吹毛求疵:这是C#5.0的一个特性,而不是.NET4.5。@Jeroen,谢谢!这太完美了。除此之外,我还可以使用基于Roslyn的扩展来确保在每个函数开始时调用此方法。@JeroenvanLangen是的,该属性来自.Net 4.5,但这不是重要的部分,它是。您可以使用C#5.0和.Net 4.0中提供属性的调用方信息。相反,调用方信息在C#4.0和.Net 4.5中不起作用,即使属性可用。@svick A,
*light bulb*
你说得对。C#5.0负责填写参数。我会改正的。感谢您的批判性阅读。挑剔:这是C#5.0的一个特性,而不是.NET4.5。@Jeroen,谢谢!这太完美了。除此之外,我还可以使用基于Roslyn的扩展来确保在每个函数开始时调用此方法。@JeroenvanLangen是的,该属性来自.Net 4.5,但这不是重要的部分,它是。您可以使用C#5.0和.Net 4.0中提供属性的调用方信息。相反,调用方信息在C#4.0和.Net 4.5中不起作用,即使属性可用。@svick A,
*light bulb*
你说得对。C#5.0负责填写参数。我会改正的。谢谢你的批判性阅读。