What you are facing is related into co- and contravariance. In general this means that generic type parameters can only implicitly converted into certain generalizations or specializations under special circumstances.
You can challange this problem from two sides: explicitly convert your types at runtime or simplify your design.
The first way is easier to apply, but since you are solving the problem at runtime, it may not be the best solution in your case.
public EmailChartGenerator(List<Email> dataList, TimeType timeType, DateTime startDate, DateTime stopDate) : base()
{
_startDate = startDate;
_stopDate = stopDate;
_datalist = dataList.ConvertAll(e => (IObject)e);
_timeType = timeType;
}
For more information read on here.
The second way is to determinate the nature of your base collection. If you only want to collect some data within a collection and initialize it from an random collection, use IEnumerable
:
public abstract class ChartHelper
{
protected IEnumerable<IObject> _datalist;
public ChartHelper()
{
_datalist = new List<IObject>();
}
public ChartHelper(IEnumerable<IObject> data)
{
_datalist = data;
}
}
Since IEnumerable
is covariant, you can implement your constructor like this:
public EmailChartGenerator(List<Email> dataList, TimeType timeType, DateTime startDate, DateTime stopDate)
: base(dataList)
{
_startDate = startDate;
_stopDate = stopDate;
_timeType = timeType;
}
However you can also easily maintain a list within your base class and initialize it from your collection:
public abstract class ChartHelper
{
protected List<IObject> _datalist;
public ChartHelper()
{
_datalist = new List<IObject>();
}
public ChartHelper(IEnumerable<IObject> data)
{
_datalist = new List<IObject>(data);
}
}
Sure you can further improve this design, but in general it should do exactly what you want.