所以我有WPf
个应用程序和Log4Net
所以每次我想添加log
时我都会这样添加:
log4net.Info("bla bla");
此外,我想添加记录器form
,因此我创建了另一个form
,并从我的主form
我打开它:
LoggerForm loggerForm = new LoggerForm();
loggerForm.Show();
并创建Log object
:
public class LogEntry : PropertyChangedBase
{
public string DateTime { get; set; }
public int Index { get; set; }
public string Source{ get; set; }
public Level Level { get; set; }
public string Message { get; set; }
}
并LogHelper
将LogEvent
个对象放在List
内,并将每个LogEvent
添加到此List
中:
public static class LogHelper
{
public static ObservableCollection<LogEntry> LogEntries { get; set; }
public static bool AddLogToList { get; set; }
private static int Index;
public static void AddLog(Level level, string message, string source)
{
if (AddLogToList)
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
if (LogEntries.Count == 1000)
LogEntries.RemoveAt(0);
LogEntry logEntry = new LogEntry()
{
DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff"),
Index = Index++,
Level = level,
Source = source,
Message = message.Trim()
};
LogEntries.Add(logEntry);
}));
}
}
}
在form
注册到我的列表InitializeComponent
之后,从我的记录器CollectionChanged
开始:
LogHelper.AddLogToList = true;
LogHelper.LogEntries.CollectionChanged += LogEntries_CollectionChanged;
这一行:
LogHelper.AddLogToList = true;
表示我的记录器form
已打开,因此我可以插入LogEvent
iunto my List。
CollectionChanged:
每次在我的LogEvent
中添加新的List
我都会将ItemSource
更新为ListView
:
ListView lvLogger;
private void LogEntries_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
lvLogger.ItemsSource = LogHelper.LogEntries;
}
好的,这些是我的问题:
每次我想创建新的Log
时,我都会输入两次:
log.Info("bla bla");
LogHelper.AddLog(Level.Info, "bla bla", $"MyClassName\\MyMethodName");
所以你可以看到我在这里使用了两次字符串,所以我想知道使用String.Builder
代替string
是否会更好?
我还想提一下,我通过不同的线程更新我的日志。
当我的记录器form
关闭时,我注册到其结束event
并清除我的LogEvent
列表:
private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
LogHelper.AddLogToList = false;
LogHelper.LogEntries.Clear();
}
所以我的问题是我应该在这里注册我的LogEntries_CollectionChanged
事件:
LogHelper.LogEntries.CollectionChanged - = LogEntries_CollectionChanged;
或者这是多余的?
答案 0 :(得分:1)
1)如果您反复多次附加文本,则只能使用Stringbuilder。除非那是你正在做的事情,否则我只会使用一个字符串。 如果这是你正在做的事情,那么也许你不应该这样做。
查看你的代码,你似乎已经有了一个消息变量,所以我可能会对使用它两次的部分感到困惑。也许你不是在谈论消息。 我会将一个字符串传递给一个方法,并在那里的代码行中使用该变量。假设他们采用相同的方法。
log.Info(message);
LogHelper.AddLog(Level.Info, message, $"MyClassName\\MyMethodName");
2)我多次阅读这部分,令人困惑。但是,作为一般原则,如果您从不是私有成员的事件订阅事件,那么您应该取消订阅该事件以避免任何内存泄漏。因此,如果集合是由不同的窗口或其他东西新建的,那么您应该取消订阅该处理程序,以便在您不再需要该窗口的实例时可以进行垃圾收集。
通过评论中的进一步说明,很明显您可以在减少日期时间内对集合进行排序,并在顶部查看最新的日志条目。这将完全避免collectionchanged事件处理程序。收集视图的排序: https://social.technet.microsoft.com/wiki/contents/articles/26673.wpf-collectionview-tips.aspx#Sorting
经过更多解释...... 看来文本文件是用于显示的。 我认为你应该完全忘记文本文件并使用observablecollection作为循环列表。
您正在调用logentries上的add方法:
LogEntries.Add(logEntry);
它的作用是附加到该集合。您可以使用insert。
插入特定索引LogEntries.Insert(0, logEntry);
这增加了该系列的“顶级”。 我认为这也可以避免排序。 你不希望那个集合变得庞大,所以一旦你打了一个数字(比如说100),你就可以删除最旧的。
LogEntries.RemoveItem(100);
请记住首先检查您是否有超过100个条目,否则会出错。
您可能需要考虑对任何其他问题进行更全面的解释。我们只知道你告诉我们什么,人们不太可能坐在那里思考你正在做什么足够长的时间才能意识到......“嘿,这就是所有的日志和文件可能会很大”。
答案 1 :(得分:0)
使用StringBuilder
不会减少您的代码。如果您想要更少的代码,请将log4net.Info("bla bla");
放在LogHelper中,或创建同时执行这两项任务的内容。
StringBuilder
与此Andy
Stringbuilder is only worth using if you're repeatedly appending text numerous times.
更多信息 - &gt; String vs Stringbuilder