Let's say that I have a group of report types to be created and all of them inherit from base abstract class:
abstract class Report
{
public abstract void GenerateReport(IReportData data);
protected virtual string SaveReportFile(string filepath)
{
// common code to save the report file
}
}
GenerateReport()
method accepts an interface that presents a data object needed for specific type of report and is defined as:
interface IReportData
{
string ReportTitle {get; set;}
int SomeOtherProperty {get; set;}
}
Concrete implementations of reports data classes are as follows:
class ReadingsReportData : IReportData
{
public string ReportTitle {get; set;}
public int SomeOtherProperty {get; set;}
public Dictionary<DateTime, double> Readings {get; set;}
}
class CalculationReportData : IReportData
{
public string ReportTitle {get; set;}
public int SomeOtherProperty {get; set;}
public int Factor {get; set;}
public List<decimal> Calculations {get; set;}
}
Now, I have several concrete report classes that should use concrete implementation of IReportData respectively - CalculationReport needs to work on
CalculationReportData
object and ReadingsReport
should use ReadingsReportData
object
class CalculationReport : Report
{
public override void GenerateReport(IReportData data)
{
CalculationReportData cdata = data as CalculationReportData;
// do something with cdata
}
}
class ReadingsReport : Report
{
public override void GenerateReport(IReportData data)
{
ReadingsReportData rdata = data as ReadingsReportData;
// do something with rdata
}
}
To get to required ReportData
object for every report type, I have to cast interface to desired concrete implementation class, which is not nice.
What are my options to change the design so that I would not need to perform that cast?
IReportData
interface?