在编译之前将代码插入C#方法
我有几个方法是从WinForms应用程序的入口点调用的。这些方法依次调用其他方法,有时也相互调用 在每个方法的输入处,我插入了如下代码:在编译之前将代码插入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
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负责填写参数。我会改正的。谢谢你的批判性阅读。