0

I'm creating a form to manage the reports of my application, the idea is that every report form inherits from this base form. My problem is that it contains several properties that HAVE to be assigned and i need to verify on every child form if I already called all, so... I'm wondering if there is a way to automatically make a call to all those properties.

This is part of the controller code:

public abstract partial class ReportsController()
{
    public string Table{ get; set; }
    public string Fields{ get; set; }
    public string Condition{ get; set; }
    public string Group{ get; set; }
    public string Order{ get; set; }
    public DataGridViewColumnCollection Columns{ get; set; }
    public SortedList<string, string> ComboboxFields{ get; set; }
    etc...

    protected abstract void New();
    protected abstract void Edit();
    protected abstract void Print();
}

As you can see, methods are not a problem, they are abstract so they will have to be declared (and thanks to Resharper i will be warned if i missed one).

Child form:

public partial class frmReportGuards : ReportsController
{
     public frmReportGuards()
     {
         code...
     }
     protected override void New()
     {
         code...
     }
     other methods...
}

And im looking for this:

public partial class frmReportGuards : ReportsController
{
     public frmReportGuards()
     {
         //Auto assigned properties.
         Table = "";
         Fields = "";
         Condition = "";
         Group = "";
         Order = "";
         Columns = new DataGridViewColumnCollection();
         ComboboxFields = new SortedList<string, string>();
     }
     protected override void New()
     {
         code...
     }
     other methods...
}

I don't know if I'm being senseless here :/ and I really need to get out of this doubt and if is possible... then simplify my work.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
a.daw
  • 21
  • 4
  • 2
    Why not add a constructor to ReportsController and set the properties there? – Pat Hensel Aug 19 '14 at 17:23
  • Is not about initializing the properties, i think I explain myself wrong, is about forcing the child classes to implement them. – a.daw Aug 19 '14 at 18:42

4 Answers4

2

If your goal is to ensure that your properties are initialized to some default value, just add a constructor to ReportsController and set the properties there.

Pat Hensel
  • 1,274
  • 9
  • 11
  • No, is about implement every property in the child classes, like @ForeverZer0 said, I might need an interface, but I didn't think about that before... – a.daw Aug 19 '14 at 18:43
  • @a.daw Ok, so just declare the properties as abstract. There's no need to create an interface. – Pat Hensel Aug 19 '14 at 21:05
  • @a.daw Defining the properties in a separate interface will only introduce unnecessary complexity. Unless the interface provides a useful abstraction of the `ReportsController` class, stick with abstract properties. – Pat Hensel Aug 19 '14 at 21:10
  • I did that, but I marked as accepted the first answer that said something about that, I appreciate a lot your help though :) – a.daw Aug 19 '14 at 21:26
1

Short answer is not in C#5.0, in C#6.0 you have Auto-Property initializers, but I think that this is not what you are looking for.

Assuming you need a parameterless constructor, you can create an Init abstract method that is called from your base constructor and do a check if your initialization missed a property. There you can throw an exception or show a visual message indicating the failure.

So in base you do:

public abstract partial class ReportsController()
{
    public ReportsController()
    {
        InitializeComponent();
        //now your method
        Init();
        CheckProperties();            
    }

    protected virtual void CheckProperties()
    {
       if(Table==null)
          addVisualErrorMessage("Table property missing");
       //and so on
    }

    protected abstract void Init();
}

But maybe you have to rethink your design and provide a single class with all the properties, so you can create an abstract method that forces you to provide all these important properties overriding a single method:

public class ComplexProperties
{
  public string Table{ get; set; }
  public string Fields{ get; set; }
  public string Condition{ get; set; }
  public string Group{ get; set; }
  public string Order{ get; set; }
  public DataGridViewColumnCollection Columns{ get; set; }
  public SortedList<string, string> ComboboxFields{ get; set; }
}

public abstract partial class ReportsController()
{
    public ComplexProperties Properties {get; private set;}

    public ReportsController()
    {
        InitializeComponent();
        //now your method
        Properties= Init();
        CheckProperties(); 
    }

    protected abstract ComplexProperties Init();
}

In any case I would prefer having a base constructor with parameters:

public abstract partial class ReportsController()
{
    public ComplexProperties Properties {get; private set;}

    public ReportsController(ComplexProperties properties)
    {
        Properties=properties;
        CheckProperties();
    }
 }

And then initialize from the constructor:

 public partial class MyReport:ReportsController
 {
    public MyReport():base(new ComplexProperties { Table="",...})
    {
    }
 }
jmservera
  • 6,454
  • 2
  • 32
  • 45
  • I appreciate the time you took to answer, but I think I didn't explain it very well... I need to force the child classes to implement the properties, not initializing them, my goal is to make sure every of them are implemented so I won't miss to assign one. – a.daw Aug 19 '14 at 18:45
  • So, if you need to enforce the implementation of the properties you can do abstract properties as well, I added another answer for this solution. – jmservera Aug 19 '14 at 20:21
1

Now I understand, if you need to enforce implementation you should do it with abstract properties, inherited classes should implement then, and can be implemented with auto-properties:

public abstract class A
{
    public abstract int MyProperty { get; set; }
}

public class B : A
{
    public override int MyProperty { get; set; }
}
jmservera
  • 6,454
  • 2
  • 32
  • 45
  • This is what I was looking for, I'm ashamed to say that I didn't know that properties could be abstract... I was going to change all my code into an interface, but this solves it in an easier way :) Thanks a lot. – a.daw Aug 19 '14 at 21:22
0

You could implement an interface for the properties that both the abstract base and the child classes need to implement.

ForeverZer0
  • 2,379
  • 1
  • 24
  • 32
  • Well I think that's exactly what I should do... all this time I've been thinking about how to implement properties with inheritance but an interface would actually solve that... thanks, I'll try it and if it works will mark as answer :) – a.daw Aug 19 '14 at 18:40