I have a number of "section items" (Lesson, Info) which inherit from the common type SectionItem. The various types of SectionItems share some but not all properties.
I have found the best way to pass parameters to each kind of object is to pack them all in a Dictionary<string, object>
and then let the base class SectionItem unpack the common ones, and each inheriting class unpack the specific ones.
This works well enough, but this is all very C#2 since I will only catch errors at runtime and not during compilation. Is there a way to do this more elegantly perhaps with generics?
using System;
using System.Collections.Generic;
using System.Text;
namespace TestPass234
{
class Program
{
static void Main(string[] args)
{
List<SectionItem> sectionItems = new List<SectionItem>();
{
Dictionary<string, object> vars = new Dictionary<string, object>();
vars.Add("sectionNumber", 1);
vars.Add("title", "Lesson #1");
vars.Add("startDate", new DateTime(2008, 12, 25));
List<Flashcard> flascards = new List<Flashcard>();
flascards.Add(new Flashcard { Question = "What color is the sky?", Answer = "blue" });
flascards.Add(new Flashcard { Question = "What color is the sun?", Answer = "yellow" });
vars.Add("flashcards", flascards);
SectionItem sectionItem = SectionItem.Instantiate("lesson", vars);
sectionItems.Add(sectionItem);
}
{
Dictionary<string, object> vars = new Dictionary<string, object>();
vars.Add("title", "Info #1");
vars.Add("content", "This is info number one.");
SectionItem sectionItem = SectionItem.Instantiate("info", vars);
sectionItems.Add(sectionItem);
}
foreach (var sectionItem in sectionItems)
{
Console.WriteLine(sectionItem.Render());
}
Console.ReadLine();
}
}
public class SectionItem
{
protected string _title;
public SectionItem()
{ }
public SectionItem(Dictionary<string, object> vars)
{
_title = Convert.ToString(vars["title"]);
}
public static SectionItem Instantiate(string idCode, Dictionary<string, object> vars)
{
switch (idCode)
{
case "lesson":
return new SectionItemLesson(vars);
case "info":
return new SectionItemInfo(vars);
default:
return new SectionItem();
}
}
public virtual string Render()
{
return "undefined section item";
}
}
public class SectionItemLesson : SectionItem
{
private int _sectionNumber;
private DateTime _startDate;
private List<Flashcard> _flashcards = new List<Flashcard>();
public SectionItemLesson(Dictionary<string, object> vars) : base(vars)
{
_sectionNumber = Convert.ToInt32(vars["sectionNumber"]);
_startDate = Convert.ToDateTime(vars["startDate"]);
_flashcards = vars["flashcards"] as List<Flashcard>;
}
public override string Render()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(">>> {0}. {1} (Starts {2:ddd, MMM d, yyyy})", _sectionNumber, _title, _startDate));
foreach (var flashcard in _flashcards)
sb.AppendLine(" - " + flashcard.Render());
return sb.ToString();
}
}
public class SectionItemInfo : SectionItem
{
private string _content;
public SectionItemInfo(Dictionary<string, object> vars)
: base(vars)
{
_content = Convert.ToString(vars["content"]);
}
public override string Render()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(">>> {0}", _title));
sb.AppendLine(String.Format(" {0}", _content));
return sb.ToString();
}
}
public class Flashcard
{
public string Question { get; set; }
public string Answer { get; set; }
public string Render()
{
return "Q: " + Question + " A: " + Answer;
}
}
}