pitersmx
pitersmx

Reputation: 957

Generics with inheritance design - need help to fix

I am having problem with my design:

I have some base class

public class ReportConfig<T> where T: class
{
    public string ReportSavePath { get; set; }
    public string ReportTitle { get; set; }
    public T ReportData { get; set; }
}

and this class can be extended into (one of possible subclass presented):

public class CsvReportConfig<T> : ReportConfig<T> where T : class
{
     // some extra class specific props
}

Then, I have a ReportGenerator abstract class

public abstract class ReportGenerator<T> where T : ReportConfig<T>
{
    public ReportGenerator(ReportConfig<T> config)
    {
        Config = config;
    }

    public ReportConfig<T> Config { get; set; }
    public abstract ReportGenerationResult GenerateReport();
}

and then, I would like to extend the ReportGenerator class into:

public class Csv1ReportGenerator : ReportGenerator<CsvReportConfig<DataObj>>
{
    public Csv1ReportGenerator (CsvReportConfig<DataObj> config) : base(config)
    {

    }

    public override ReportGenerationResult GenerateReport()
    {
        throw new NotImplementedException();
    }
}

And here, I am receiving an error that

CsvReportConfig<DataObj> cannot be used as type parameter 'T' in generic type or method ReportGenerator<T>.

What am I doing wrong and how to correct this?

Upvotes: 2

Views: 82

Answers (1)

Igor
Igor

Reputation: 62213

I believe this is what you are trying to do

public class ReportGenerationResult { }
public class DataObj { }
public class ReportConfig<T> where T : class
{
    public string ReportSavePath { get; set; }
    public string ReportTitle { get; set; }
    public T ReportData { get; set; }
}

public class CsvReportConfig<T> : ReportConfig<T> where T : class
{}

public abstract class ReportGenerator<T,U> where T : ReportConfig<U> where U : class
{
    protected ReportGenerator(T config)
    {
        Config = config;
    }

    public T Config { get; set; }
    public abstract ReportGenerationResult GenerateReport();
}
public class Csv1ReportGenerator : ReportGenerator<CsvReportConfig<DataObj>, DataObj>
{
    public Csv1ReportGenerator(CsvReportConfig<DataObj> config) : base(config)
    {
    }

    public override ReportGenerationResult GenerateReport()
    {
        throw new NotImplementedException();
    }
}

Edit

These are the main changes that were made.

  • ReportGenerator - This was the main change. It looks like you want to specify a generic type parameter for the property Config (constrained to types that are or extend ReportConfig<T>) in any implementations. To do this and to keep the ReportConfig.ReportData generic you have to use 2 generic type parameters where the second type parameter is reused to constrain ReportConfig<T>.
  • Csv1ReportGenerator - now when this inherits ReportGenerator<CsvReportConfig<DataObj>, DataObj> instead of ReportGenerator<CsvReportConfig<DataObj>> which now enables this type to have property Config which would be constrained to type CsvReportConfig<DataObj> which is what you were trying to do.

Upvotes: 4

Related Questions