【学习笔记】Silverlight框架:Jounce(3)——日志记录
日志记录在各个框架里都是差不多的。Jounce里的这个部分也比较简单。涉及的类有三个:接口ILogger、基础实现DefaultLogger和消息等级枚举LogSeverity。
ILogger中定义了4个方法,3个是用来记录日志的,还有1个是SetSeverity(LogSeverity minimumLevel)。根据DefaultLogger中的实现来看,在其内部维护了一个消息等级的变量“_severityLevel”,可以通过SetSeverity方法来进行设置,其相当于一个阈值,控制当前的日志信息要不要输出(作者本意应该是如此吧,实际应用中可以更灵活的变通)。
DefaultLogger中日志默认只是通过Debug.WriteLine输出,因此很多情况下我们需要实现自己的ILogger。
实践下吧,在Prism里有个动态加载模块例子“Open Modularity With Mef”,里面实现了一个日志类,并最终输出日志信息到UI上显示,我们来做个类似的,看看Jounce在初始化的时候会输出哪些信息。
Jounce模板创建的解决方案是没有Web项目的,这次的例子的部分功能设置需要用到Web项目,所以就不用模板创建了。整个结构如下:
CallbackLogger的代码如下:
[Export] [Export(typeof(ILogger))] public class CallbackLogger : ILogger { private LogSeverity _severityLevel; private readonly Queue<Tuple<LogSeverity, string, string>> savedLogs = new Queue<Tuple<LogSeverity, string, string>>(); public Action<LogSeverity, string, string> Callback { get; set; } public void Log(LogSeverity severity, string source, Exception exception) { if (!Debugger.IsAttached || (int)severity < (int)_severityLevel) { return; } var sb = new StringBuilder(); sb.Append(exception); var ex = exception.InnerException; while (ex != null) { sb.AppendFormat("{0}{1}", Environment.NewLine, ex); ex = ex.InnerException; } this.Log(severity, source, sb.ToString()); } public void Log(LogSeverity severity, string source, string message) { if (!Debugger.IsAttached || (int)severity < (int)_severityLevel) { return; } if (this.Callback != null) { this.Callback(severity, source, message); } else { this.savedLogs.Enqueue(new Tuple<LogSeverity, string, string>(severity, source, message)); } } public void LogFormat(LogSeverity severity, string source, string messageTemplate, params object[] arguments) { this.Log(severity, source, string.Format(messageTemplate, arguments)); } public void SetSeverity(LogSeverity minimumLevel) { _severityLevel = minimumLevel; } public void ReplaySavedLogs() { if (this.Callback != null) { while (this.savedLogs.Count > 0) { var log = this.savedLogs.Dequeue(); this.Callback(log.Item1, log.Item2, log.Item3); } } } }
整个就是DefaultLogger和Prism里的那个CallbackLogger的复合体。
阈值_severityLevel控制信息要不要输出,Callback用于输出信息,savedLogs用于存储当Callback=null时的输出信息。
当给Callback赋值后就可以调用ReplaySavedLogs方法输出savedLogs中存储的信息了。
至于头上为什么要加2个[Export]标记,我想,你懂的。
MainPage的页面内容就是只有一个TextBox用于显示输出信息:
<Grid x:Name="LayoutRoot" Background="White">
<TextBox x:Name="TraceTextBox" Margin="10" TextWrapping="Wrap"/>
</Grid>
看一下MainPage.cs:
[ExportAsView(typeof(MainPage), IsShell = true)] public partial class MainPage : UserControl, IPartImportsSatisfiedNotification { [Import] public CallbackLogger Logger { get; set; } public MainPage() { InitializeComponent(); } public void Log(LogSeverity severity, string source, string message) { this.TraceTextBox.Text += string.Format(CultureInfo.CurrentUICulture, "[{0}][{1}] {2}\r\n", severity, source, message); } public void OnImportsSatisfied() { this.Logger.SetSeverity(LogSeverity.Verbose); this.Logger.Callback = this.Log; this.Logger.ReplaySavedLogs(); } }
标记[ExportAsView]指定这是一个输出视图,并且是Shell,这样程序启动的时候就会把Application.Current.RootVisual设为MainPage了,具体以后再说。
程序启动的时候会去启动页里读取LogLevel参数,并调用Ilogger.SetSeverity方法,如果没有获取到参数,默认的Level是LogSeverity.Warning,比较高,而我们这次需要看一下所有的信息,所以在模块加载完的时候需要重新设一下this.Logger.SetSeverity(LogSeverity.Verbose)。
运行下看看:
再回头来看一下如何在启动页里配置LogLevel,打开LoggerTestPage.html,找到Host添加信息如下:
试一下,你能看到更多的调试信息。
半路和尚 by 超时空饭盒 is licensed under a Creative Commons 署名-非商业性使用-相同方式共享 3.0 Unported License.
基于halfwaymonk.cnblogs.com上的作品创作。