为什么 XmlWriter.Create() 对 Rss20FeedFormatter 和 SyndicateFeed 的测试失败?
下面的测试通过只是因为使用了 new XmlTextWriter(sw)
而不是 XmlWriter.Create(sw, settings) 或 XmlTextWriter.Create(sw)
:
public void ShouldGenerateRssFeed()
{
//reference: [http://dotnetslackers.com/articles/aspnet/How-to-create-a-syndication-feed-for-your-website.aspx]
var items = new List<SyndicationItem>
{
new SyndicationItem
{
Content = TextSyndicationContent.CreatePlaintextContent("This is plain test content for first item."),
PublishDate = DateTime.Now,
Summary = TextSyndicationContent.CreatePlaintextContent("Item summary for first item…"),
Title = TextSyndicationContent.CreatePlaintextContent("First Item Title")
},
new SyndicationItem
{
Content = TextSyndicationContent.CreatePlaintextContent("This is plain test content for second item."),
PublishDate = DateTime.Now,
Summary = TextSyndicationContent.CreatePlaintextContent("Item summary for second item…"),
Title = TextSyndicationContent.CreatePlaintextContent("Second Item Title")
},
new SyndicationItem
{
Content = TextSyndicationContent.CreateXhtmlContent("This is <strong>XHTML</strong> test content for <em>third</em> item."),
PublishDate = DateTime.Now,
Summary = TextSyndicationContent.CreatePlaintextContent("Item summary for third item…"),
Title = TextSyndicationContent.CreatePlaintextContent("Third Item Title")
}
};
var feed = new SyndicationFeed(items);
Assert.IsTrue((new List<SyndicationItem>(feed.Items)).Count == 3, "The expected number of Syndication items is not here.");
feed.Items.ForEachInEnumerable(i =>
{
i.Authors.Add( new SyndicationPerson
{
Email = "[email protected]",
Name = "Bryan Wilhite",
Uri = "http://SonghaySystem.com"
});
});
var formatter = new Rss20FeedFormatter(feed);
var settings = new XmlWriterSettings
{
Encoding = Encoding.UTF8,
Indent = true,
IndentChars = " "
};
var buffer = new StringBuilder();
var output = string.Empty;
using(var sw = new StringWriter(buffer))
{
var writer = new XmlTextWriter(sw); //XmlWriter.Create(sw, settings) or XmlTextWriter.Create(sw) fails here!
formatter.WriteTo(writer);
output = buffer.ToString();
TestContext.WriteLine(output);
}
Assert.IsTrue(!output.Equals(string.Empty), "The expected output is not here.");
}
顺便说一下,在上面的示例中,我使用了扩展方法 ForEachInEnumerable
:
/// <summary>
/// Extensions for <see cref="System.Collections.Generic.IEnumerable<T>"/>.
/// </summary>
public static class IEnumerableOfTExtensions
{
/// <summary>
/// Performs the <see cref="System.Action"/>
/// on each item in the enumerable object.
/// </summary>
/// <typeparam name="TEnumerable">The type of the enumerable.</typeparam>
/// <param name="enumerable">The enumerable.</param>
/// <param name="action">The action.</param>
/// <remarks>
/// “I am philosophically opposed to providing such a method, for two reasons.
/// …The first reason is that doing so violates the functional programming principles
/// that all the other sequence operators are based upon. Clearly the sole purpose of a call
/// to this method is to cause side effects.”
/// —Eric Lippert, “foreach” vs “ForEach” [http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx]
/// </remarks>
public static void ForEachInEnumerable<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> action)
{
foreach(var item in enumerable)
{
action(item);
}
}
}
The following test below passes only because new XmlTextWriter(sw)
is used instead of XmlWriter.Create(sw, settings) or XmlTextWriter.Create(sw)
:
public void ShouldGenerateRssFeed()
{
//reference: [http://dotnetslackers.com/articles/aspnet/How-to-create-a-syndication-feed-for-your-website.aspx]
var items = new List<SyndicationItem>
{
new SyndicationItem
{
Content = TextSyndicationContent.CreatePlaintextContent("This is plain test content for first item."),
PublishDate = DateTime.Now,
Summary = TextSyndicationContent.CreatePlaintextContent("Item summary for first item…"),
Title = TextSyndicationContent.CreatePlaintextContent("First Item Title")
},
new SyndicationItem
{
Content = TextSyndicationContent.CreatePlaintextContent("This is plain test content for second item."),
PublishDate = DateTime.Now,
Summary = TextSyndicationContent.CreatePlaintextContent("Item summary for second item…"),
Title = TextSyndicationContent.CreatePlaintextContent("Second Item Title")
},
new SyndicationItem
{
Content = TextSyndicationContent.CreateXhtmlContent("This is <strong>XHTML</strong> test content for <em>third</em> item."),
PublishDate = DateTime.Now,
Summary = TextSyndicationContent.CreatePlaintextContent("Item summary for third item…"),
Title = TextSyndicationContent.CreatePlaintextContent("Third Item Title")
}
};
var feed = new SyndicationFeed(items);
Assert.IsTrue((new List<SyndicationItem>(feed.Items)).Count == 3, "The expected number of Syndication items is not here.");
feed.Items.ForEachInEnumerable(i =>
{
i.Authors.Add( new SyndicationPerson
{
Email = "[email protected]",
Name = "Bryan Wilhite",
Uri = "http://SonghaySystem.com"
});
});
var formatter = new Rss20FeedFormatter(feed);
var settings = new XmlWriterSettings
{
Encoding = Encoding.UTF8,
Indent = true,
IndentChars = " "
};
var buffer = new StringBuilder();
var output = string.Empty;
using(var sw = new StringWriter(buffer))
{
var writer = new XmlTextWriter(sw); //XmlWriter.Create(sw, settings) or XmlTextWriter.Create(sw) fails here!
formatter.WriteTo(writer);
output = buffer.ToString();
TestContext.WriteLine(output);
}
Assert.IsTrue(!output.Equals(string.Empty), "The expected output is not here.");
}
By the way, I'm using an extension method, ForEachInEnumerable
, in the sample above:
/// <summary>
/// Extensions for <see cref="System.Collections.Generic.IEnumerable<T>"/>.
/// </summary>
public static class IEnumerableOfTExtensions
{
/// <summary>
/// Performs the <see cref="System.Action"/>
/// on each item in the enumerable object.
/// </summary>
/// <typeparam name="TEnumerable">The type of the enumerable.</typeparam>
/// <param name="enumerable">The enumerable.</param>
/// <param name="action">The action.</param>
/// <remarks>
/// “I am philosophically opposed to providing such a method, for two reasons.
/// …The first reason is that doing so violates the functional programming principles
/// that all the other sequence operators are based upon. Clearly the sole purpose of a call
/// to this method is to cause side effects.”
/// —Eric Lippert, “foreach” vs “ForEach” [http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx]
/// </remarks>
public static void ForEachInEnumerable<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> action)
{
foreach(var item in enumerable)
{
action(item);
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我
使用了
错误的Disposable对象:StringBuilder
不需要StringWriter
——并且我未能刷新XmlWriter< /code> (这是一种可以追溯到 .NET 2.0 的做法):
I was
using
the wrong Disposable object: theStringBuilder
did not need aStringWriter
---and I failed to Flush theXmlWriter
(which is a practice that dates back to .NET 2.0):