假设这个类:
public class Logger
{
static TextWriter fs = null;
public Logger(string path)
{
fs = File.CreateText(path);
}
public static void Log(Exception ex)
{
///do logging
}
public static void Log(string text)
{
///do logging
}
}
我必须使用它:
Logger log = new Logger(path);
然后使用Logger.Log()
记录我想要的内容。我只使用一台记录仪。
问题是:这是一个很好的设计吗?实例化一个类然后总是调用它的静态方法?任何有关更好设计的建议产量都表示赞赏。
根据Marc的答案进行修改:
我在日志的最后一行刷新,并且在打开时不需要我读取文件,文件未完全关闭的问题是正确的。这个类只是满足我的要求,并且不需要线程安全。我只想阅读实例化部分,我应该进入你说的SetPath,关闭文件的任何建议吗?
答案 0 :(得分:3)
是的,有一个构造函数只是为了这个是糟糕的设计。一个静态的SetPath
方法可以只调用一次(否则抛出异常)似乎更好。您可以在app-startup等期间设置路径
然后,如果需要满足某些基于接口的方案,您可以将其设为static class
或单例。
下一步:你必须在这里添加同步!这不是线程安全的。如果两个线程同时尝试登录,我预计会崩溃。它不需要复杂;最简单的:
private readonly object syncLock = new object();
public static void Log(string value) {
lock(syncLock) {
//...
}
}
(但请注意,这可能会产生一些阻止成本;可以使用更复杂的代码进行改进 - 见下文)
现有的日志记录库会考虑更多问题 - 文件分区,异步(以阻止代码被IO阻止),批处理等;为什么不只使用其中之一?特别是,在te-moment,您的文件将不会在app-exit处完全关闭,不会定期刷新,并且会在大多数时间保持文件锁定状态。不好。
答案 1 :(得分:3)
不,这没有意义。每次实例化Logger时,都会覆盖静态TextWriter,这将影响该类的所有使用者。如果你想保留实例构造函数,那么你应该让TextWriter成为一个实例字段,方法应该是实例方法。
作为替代方案,您可能需要考虑使用log4net,它将为您执行此类日志记录工作。
答案 2 :(得分:0)
我认为你应该使用静态属性使整个类静态,允许你设置日志路径。
public static class Logger
{
static TextWriter fs = null;
public static string FileName
{
set
{
fs = File.CreateText(value);
}
}
public static void Log(Exception ex)
{
if(fs == null) return;
///do logging
}
public static void Log(string text)
{
if(fs == null) return;
///do logging
}
}