-1

I couldn't come up with better title. I will try to explain what the problem is.

Currently I am trying to build dynamically created report structure. I define needed report in config file. When user wants to a report I simply parse from config and create. The struggle I have is about how I can implement a general structure but covers extra fields provided by interfaces.

In the image you can see the class diagram. What I want is I want to use ReportStore for storing all shared and extensive reports and providing when needed. However In ReportStore when user call GetReportByName(reportName) I need to return a ReportObject. This object may be SharedReport or ExtensiveReport.

  • To use ISharedReport for return value will cause losing extra field in objects based on IExtensiveReport.
  • If i want to return IExtensiveReport it will violate.
  • If I want to return plain object and cast in ReportComposer according to value type will be complex and not developer friendly.

I am open for suggestion. Thank you in advance

Sample Class Diagram

1
  • 1
    Could you elabroate a bit? From my perspective it is unclear what the concrete business usecases are for what you are modeling. There are several roads to go down. I am not sure if your basic model is the best design choice. Sep 15, 2017 at 11:13

1 Answer 1

0

If I understand you correctly, then I faced a similar problem recently and I solved it this way (not that I believe this is necesarily the best way to do it) (Note C#-ish code ahead)

IBaseReport
{
   ReportTypeEnum ReportType { get; }
   // Other common stuff EG
   Print() ..
   GetDetails() ..
}

ISharedReport : IBaseReport
{
  // Shared report only stuff
}

IExtensiveReport : IBaseReport
{
  // Extensive report only stuff
}

abstract class BaseReport
{
  ReportTypeEnum ReportType { get; private set; }
}

class ExtensiveReport : BaseReport, IExtensiveReport
{
  public SharedReport()
  {
     ReportType = ReportTypeEnum.Extensive;
  }
}


class SharedReport : ExtensiveReport, ISharedReport
{
  public SharedReport() 
  {
     ReportType = ReportTypeEnum.Shared;
  }
}



List<IBaseReport> DataStore = new List<IBaseReport>();
DataStore.Add(new ExtensiveReport());
DataStore.Add(new SharedReport());
etc ..

var report1 = DataStore[0];
report1.Print();

var report2 = DataStore[1] as ISharedReport;
if (report2 != null)
{
  // do SharedReport specific stuff
}

And then I only store/return IBaseReport objects. These objects know what type they are so you don't need to cast them to anything when you use them via the common interface. But if you need class specific functionality you can safely down cast to the required interface (ISharedReport or IExtensiveReport objects) and if the object does not support that interface your casting mechanism will let you know that - however if the base interface is sufficient you should not need to down cast.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.