我无法摆脱这个问题。这是非常有趣的,当我尝试在调试模式下运行我的NUnit测试时,我得到了预期的结果,但是当我正常运行时,结果是错误的。
我试图做的是检测绑定错误。这是一个样本
[TestFixture, RequiresSTA]
public class BindingTests
{
[Test]
public void T1_BindingErrorsExpected()
{
string error = null;
using (var listener = new ObservableTraceListener())
{
listener.TraceCatched += s => error = s;
TextBlock myText = new TextBlock();
UserControl control = new UserControl();
Binding myBinding = new Binding("BadBinding");
myBinding.Source = control;
myText.SetBinding(TextBlock.BackgroundProperty, myBinding);
}
Assert.IsNotNull(error);
}
}
ObservableTraceListener
public sealed class ObservableTraceListener : DefaultTraceListener
{
private readonly StringBuilder _Builder = new StringBuilder();
public ObservableTraceListener()
{
PresentationTraceListener.Add(SourceLevels.Error, this);
}
public new void Dispose()
{
Flush();
Close();
PresentationTraceListener.Remove(this);
base.Dispose();
}
public override void Write(string message)
{
_Builder.Append(message);
}
public override void WriteLine(string message)
{
Write(message);
if (TraceCatched != null)
TraceCatched(_Builder.ToString());
_Builder.Clear();
}
public event Action<string> TraceCatched;
}
public static class PresentationTraceListener
{
public static void Add(SourceLevels level, TraceListener trace)
{
PresentationTraceSources.DataBindingSource.Listeners.Add(trace);
PresentationTraceSources.DataBindingSource.Switch.Level = level;
PresentationTraceSources.ResourceDictionarySource.Listeners.Add(trace);
PresentationTraceSources.ResourceDictionarySource.Switch.Level = level;
}
public static void Remove(TraceListener trace)
{
PresentationTraceSources.DataBindingSource.Listeners.Remove(trace);
PresentationTraceSources.ResourceDictionarySource.Listeners.Remove(trace);
}
}
调试结果 - &gt;失败(我的期望)
运行结果 - >成功(不是预期的)
答案 0 :(得分:1)
感谢MatthewMartin,但我找到了https://github.com/bblanchon/WpfBindingErrors
的解决方案探测器是我的ObservableTraceListener
。
我需要添加一个静态构造函数来调用PresentationTraceSources.Refresh()
以使其正常工作。如MSDN doc中所述,它Refreshes trace sources, by forcing the app.config file to be re-read
。因此,当我在“调试”模式下启动测试时,刚刚完成了一些初始化,这可能导致app.config文件被读取。
MSDN doc - &gt; PresentationTraceSources.Refresh()http://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.refresh%28v=vs.100%29.aspx
以下是我的最终ObservableTraceListener
,PresentationTraceListener
与问题中的public sealed class ObservableTraceListener : TraceListener
{
private readonly StringBuilder _Builder = new StringBuilder();
static ObservableTraceListener()
{
PresentationTraceSources.Refresh();
}
public ObservableTraceListener()
{
PresentationTraceListener.Add(SourceLevels.Error, this);
}
public new void Dispose()
{
Flush();
Close();
PresentationTraceListener.Remove(this);
base.Dispose();
}
public override void Write(string message)
{
_Builder.Append(message);
}
public override void WriteLine(string message)
{
_Builder.Append(message);
if (TraceCatched != null)
TraceCatched(_Builder.ToString());
_Builder.Clear();
}
public event Action<string> TraceCatched;
}
相同
{{1}}
答案 1 :(得分:0)
发布答案,因为评论太小而无法保持我想说的内容......
Internet上没有对PresentationTraceListener的引用 - 它如何处理TraceListener很重要,因为AFAIK的PresentationTraceListener调用TraceListener的Write / WriteLine方法(可能通过TraceSource间接调用)
以下代码汇编了一个全新的项目。如果我写(x),我得到null,如果我写了线(x),我得到一个值。通常,当您编写自定义TraceListener时,将所有重载重定向到单个方法,以使它们的行为相同(Write和WriteLine应该相同,除了WriteLine在调用者的消息上添加换行符。)
另一个观察结果是,System.Diagnostics跟踪是一个古怪的日志记录库,其主要优点是即使在使用第三方库时存在一些障碍时它也始终可用。 System.Diagnostics跟踪确实希望您在app.config或web.config中注册TraceSwitch,TraceListener并使用它来启用&amp;禁用跟踪。它还要求注册TRACE标志(以相同的方式注册DEBUG标志,在项目中的特性 - 默认为DEBUG和RELEASE定义TRACE)
[TestFixture, RequiresSTA]
public class BindingTests
{
[Test]
public void T1_BindingErrorsExpected()
{
string error = null;
using (var listener = new ObservableTraceListener())
{
listener.TraceCatched += s => error = s;
//TextBlock myText = new TextBlock();
//UserControl control = new UserControl();
//Binding myBinding = new Binding("BadBinding");
//myBinding.Source = control;
//myText.SetBinding(TextBlock.BackgroundProperty, myBinding);
PresentationTraceSources.DataBindingSource.TraceEvent(TraceEventType.Error,0, "Hello World!");
}
Assert.IsNotNull(error);
Console.WriteLine(error);
}
}
public sealed class ObservableTraceListener : TraceListener
{
private readonly StringBuilder _Builder = new StringBuilder();
public ObservableTraceListener()
{
//PresentationTraceListener.Add(SourceLevels.Error, this);
}
protected override void Dispose(bool disposing)
{
Flush();
Close();
//PresentationTraceListener.Remove(this);
}
public override void Write(string message)
{
_Builder.Append(message);
}
public override void WriteLine(string message)
{
Write(message);
if (TraceCatched != null)
TraceCatched(_Builder.ToString());
_Builder.Clear();
}
public event Action<string> TraceCatched;
}