5

请查看我的以下代码...

public enum LogType
{
    Debug,
    Info,
    Warn,
    Error,
    Fatal
}

private static readonly ILog log = 
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

public void LogError(LogType logtype, string message)
{
    XmlConfigurator.Configure();
    if (logtype == LogType.Debug)
        log.Debug(message);
    else if (logtype == LogType.Error)
        log.Error(message);
}

我不喜欢上面所有的 if-else 语句,并相信有一种更简洁的方式来编写它。我该如何重构它?日志类有不同的调试、错误等方法。

我想对一个方法进行一次调用,让它自动处理它。

LogMyError(LogType.Debug, "I am just logging here");

我怎么能做这样的事情?我更喜欢远离 switch 语句。我正在寻找一种干净的面向对象的方法。

4

6 回答 6

16

你的代码完全没问题;我不会改变它。

但是,如果您想对它更加“面向对象”,那么考虑一下如何做到这一点是很有启发性的。让我们考虑您的两个案例;其他的你可以很容易地看到它们是如何实现的:

public abstract class LogType
{
    public static readonly LogType Debug = new LogTypeDebug();
    public static readonly LogType Error = new LogTypeError();

    private LogType() {} // Prevent anyone else from making one.

    public abstract void LogMessage(ILog logger, string message);

    private sealed class LogTypeDebug: LogType
    {
        public override void LogMessage(ILog logger, string message)
        {
            logger.Debug(message);
        }
    }

    private sealed class LogTypeError: LogType
    {
        public override void LogMessage(ILog logger, string message)
        {
            logger.Error(message);
        }
    }
}
...

//Obtain the log object the way you prefer.
private static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

public void LogError(LogType logtype, string message)
{
    logtype.LogMessage(log, message);
}

呼叫站点根本没有改变!它仍然看起来像:

LogError(LogType.Debug, "my message");

你去了:根本没有ifswitch声明!“切换类型”代码已移至虚函数表中,这是它在面向对象代码中所属的位置。

A nice side effect of this technique is you never need to worry about someone casting an integer to an unsupported value of your enumerated type. The only possible values for a variable of type LogType are null or a reference to one of the singletons.

于 2012-04-05T21:07:54.193 回答
11

您可以使用 aDictionary<LogType,Action<string>>来保存对每个枚举值执行的操作,然后只需调用委托。

var logActions = new Dictionary<LogType,Action<string>>();
logActions.Add(LogType.Debug, log.Debug);
...

logActions[logtype](message);

更新:

if如果您的语句中只有少量分支,这一切都过大了。我会将此方法用于 5+ 个这样的 if。

于 2012-04-05T20:51:53.857 回答
5

Imo,没有任何明显的理由来更改您的代码中的任何内容。功能明确,if/else定义明确。函数声明允许您以您只想使用它的方式使用它。

所以我不会更改我看到的代码中的任何内容。

祝你好运。

于 2012-04-05T20:52:37.370 回答
3

使用开关块

switch (logtype)
{
    case LogType.Debug:
        log.Debug(message);
        break;

    case LogType.Error:
        log.Error(message);
        break;

    //more cases here as needed...

    default:
        throw new InvalidArgumentException("logtype");
}
于 2012-04-05T20:50:04.220 回答
0

总是有这样的switch说法:

switch (logtype)
{
    case LogType.Debug:
        log.Debug(message);
        break;
    case LogType.Error:
        log.Error(message);
        break;
    ....
}
于 2012-04-05T20:50:28.730 回答
0

您可以使用 a或使用as 键和相应的方法作为值switch创建字典- an ,然后执行LogTypeLogXXXXAction<string>

myDictionary[logType](message);
于 2012-04-05T20:53:56.647 回答