Рассмотрите возможность инвертирования логики управления и предоставления виртуального метода Render () в NewsItem. Э.Г.
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);
}
}
Edit:
Альтернативная техника
Точка, взятая о комментариях от других повторного разделения проблем. Я не знаю, установлен ли вы на IRenderer по другим причинам, но если нет, есть еще один метод, который не требует использования отражения. Вместо этого вы можете использовать шаблон Visitor.
Сначала вы объявляете класс NewsItemVisitor:
public abstract class NewsItemVisitor
{
public abstract void Visit(NewsItemJoiner joiner);
public abstract void Visit(NewsItemStatus status);
}
Затем добавьте виртуальный метод Accept () в NewsItem (для этого примера я изменил ваши типы данных на строковые вместо 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