【问题标题】:How do I alter code at compile time based on a flag in C#如何在编译时根据 C# 中的标志更改代码
【发布时间】:2014-10-07 06:19:02
【问题描述】:

我想设置一个调试标志,以便将“Console”.Writeline 替换为“Log”.WriteLine。 不想写了

if (debug)
    Log.writeline("log");
else 
    Console.Writeline("log"); every time I want to log info.

类似于INFO.Writelline("log"); 的东西,其中 INFO 可以替换为“Log”或“Console”,具体取决于全局变量集。
会使用条件宏,但 C# 不支持。 如果我遗漏了什么,请告诉我。

【问题讨论】:

  • 您是否可以创建一个静态方法来抽象您可以使用的分支逻辑。例如: public static void DebugLog(string log) { if (debug) Log.writeline(log);否则 Console.WriteLine(log); }
  • 为什么你不能使用正常的Trace 功能,让你几乎可以做到这一点(除了在运行时通过配置文件进行配置)?
  • "会使用条件宏,但 C# 不支持" -- 是什么让你产生了这个想法? C# 预定义的符号可能不如 C 的宏强大,但一个简单的#if 是可能的。
  • 在我们的源代码上运行 C++ 预处理器首先对您有用(我不会为任何新代码这样做,但在重构代码时可能是可接受的解决方法...)
  • @ALexei:感谢您的输入。但这将涉及对象的附加参数。只需要传递消息。

标签: c# debugging conditional-compilation visual-studio-macros


【解决方案1】:

你有没有尝试过这样的事情:

 #if (DEBUG)
      Log.writeline("log");
 #else
     Console.Writeline("log");
 #endif

【讨论】:

  • 请注意,这几乎正是 OP 所说的“我不想写 if (...)。每个跟踪行仍然有多行代码 - 不是真正的解决方案。
【解决方案2】:

这样的?

#define MY_DEBUG //Note: this must be the first line in the file

public static class INFO
{
    public static void WriteLine(string message)
    {
         #if (MY_DEBUG)
             Log.writeline(message);
         #else
             Console.Writeline(message);
         #endif
    }
}

你会打电话给

INFO.WriteLine("log message");

【讨论】:

  • 是否完全满足 OP 的要求,+1,包括未知的等效“条件宏”。
【解决方案3】:

您可以使用Log4Net 之类的库并设置不同的附加程序,一个用于控制台,一个用于记录到文件/sql 服务器等。

<log4net>
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
        <file value="log-file-1.txt" />
        <appendToFile value="true" />
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date %message%newline" />
        </layout>
    </appender>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
    </layout>
</appender>

    <root>
        <level value="DEBUG" />
        <appender-ref ref="FileAppender" />
        <appender-ref ref="ConsoleAppender" />
    </root>
</log4net>

通过这样做,您将看到它在本地运行时记录到控制台,并且在生产中运行时也会记录到文件,这将在同一行完成...

log.info(...);

【讨论】:

    【解决方案4】:

    没有直接回答你的问题。但是您可以添加自己的界面ILog 并避免到处出现if(debug) 条件..

    public interface ILog
    {
        void WriteLine(string message);
    }
    

    然后像这样实现它

    public class LogImpl : ILog
    {
        public void WriteLine(string message)
        {
            Log.WriteLine(...);
        }
    }
    
    public class DebugImpl : ILog
    {
        public void WriteLine(string message)
        {
            Debug.WriteLine(...);
        }
    }
    

    那么为方便起见,您可以有一个提供此实例的静态类。

    public static class Logger
    {
        public static ILog Instance = new DebugImpl();//Or LogImpl 
    }
    

    那你可以说

    Logger.Instance.WriteLine(...);
    

    优点是您可以在运行时在不同的实现之间切换。比如DebugConsoleFileDatabase等等。

    【讨论】:

    • 您将如何在运行时切换实现?
    • @christiandev 这不就是Logger.Instance = new OtherILogImpl()吗?当你想切换时,只需将其设置为新实例即可。
    • 我知道它可以在设计时完成,但我不确定如何在运行时实现?
    • @christiandev 我不明白。是什么阻止您在运行时执行它?您可以随时通过Logger.Instance = new ILogImpl(); 更改实例,这只是您可以随时设置的字段或属性。从那时起,它的行为就会有所不同。
    • 我的意思是,例如,您的应用程序在服务器上运行;还是建议您在本地运行应用程序,然后停止应用程序,更改实现,重新启动应用程序?
    猜你喜欢
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 2014-02-01
    • 2012-07-05
    • 2015-07-04
    • 1970-01-01
    相关资源
    最近更新 更多