考虑反转控制逻辑并在 NewsItem 中提供虚拟 Render() 方法。例如
abstract class NewsItem {
// ...
public virtual string Render() { return string.Empty; }
}
然后你的子类可以根据需要实现:
public class NewsItemJoiner : NewsItem
{
// ...
public override string Render() {
return String.Format("{0} has just joined our music network.", this.AccountJoined.ArtistName);
}
}
编辑:
替代技术
关于 cmets 与其他人重新分离关注点的观点。我不知道您是否出于其他原因设置了 IRenderer,但如果不是,还有另一种不需要使用反射的技术。您可以改用访问者模式。
首先你声明一个 NewsItemVisitor 类:
public abstract class NewsItemVisitor
{
public abstract void Visit(NewsItemJoiner joiner);
public abstract void Visit(NewsItemStatus status);
}
接下来,为 NewsItem 添加一个虚拟 Accept() 方法(在本例中,我已将您的数据类型更改为字符串,而不是 Account、Status 等):
public abstract class NewsItem
{
public virtual string Account { get; set; }
public virtual DateTime DateTime { get; set; }
public abstract void Accept(NewsItemVisitor visitor);
}
public class NewsItemJoiner : NewsItem
{
public virtual string AccountJoined { get; set; }
public override void Accept(NewsItemVisitor visitor)
{
visitor.Visit(this);
}
}
public class NewsItemStatus : NewsItem
{
public virtual string Status { get; set; }
public override void Accept(NewsItemVisitor visitor)
{
visitor.Visit(this);
}
}
现在您可以创建一个具体的访问者,这是我们的渲染器:
public class NewsItemListRenderer : NewsItemVisitor
{
private readonly List<NewsItem> itemList;
private string renderedList = string.Empty;
public NewsItemListRenderer(List<NewsItem> itemList)
{
this.itemList = itemList;
}
public string Render()
{
foreach (var item in itemList)
{
item.Accept(this);
}
return renderedList;
}
public override void Visit(NewsItemJoiner joiner)
{
renderedList += "joiner: " + joiner.AccountJoined + Environment.NewLine;
}
public override void Visit(NewsItemStatus status)
{
renderedList += "status: " + status.Status + Environment.NewLine;
}
}
如何呈现 NewsItem 实例列表的示例代码:
List<NewsItem> itemList = new List<NewsItem>();
itemList.Add(new NewsItemJoiner { AccountJoined = "fred" });
itemList.Add(new NewsItemJoiner { AccountJoined = "pete" });
itemList.Add(new NewsItemStatus { Status = "active" });
itemList.Add(new NewsItemJoiner { AccountJoined = "jim" });
itemList.Add(new NewsItemStatus { Status = "inactive" });
NewsItemListRenderer renderer = new NewsItemListRenderer(itemList);
Console.WriteLine(renderer.Render());
运行它会得到以下输出:
joiner: fred
joiner: pete
status: active
joiner: jim
status: inactive