Diciamo che ho un gruppo di tipi di report da creare e tutti ereditano dalla classe abstract di base:
abstract class Report
{
public abstract void GenerateReport(IReportData data);
protected virtual string SaveReportFile(string filepath)
{
// common code to save the report file
}
}
Il metodo GenerateReport()
accetta un'interfaccia che presenta un oggetto dati necessario per un tipo specifico di report ed è definito come:
interface IReportData
{
string ReportTitle {get; set;}
int SomeOtherProperty {get; set;}
}
Le implementazioni concrete delle classi di dati dei rapporti sono le seguenti:
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;}
}
Ora ho diverse classi di report concreti che dovrebbero utilizzare l'implementazione concreta di IReportData rispettivamente - CalculationReport deve lavorare su
CalculationReportData
oggetto e ReadingsReport
dovrebbero usare ReadingsReportData
oggetto
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
}
}
Per ottenere l'oggetto ReportData
richiesto per ogni tipo di rapporto, devo eseguire il cast dell'interfaccia alla classe di implementazione concreta desiderata, che non è piacevole.
Quali sono le mie opzioni per modificare il design in modo tale da non dover eseguire quel cast?