在继承形式中自动实现属性

本文关键字:实现 属性 继承 | 更新日期: 2023-09-27 18:18:53

我正在创建一个表单来管理我的应用程序的报表,其想法是每个报表表单都继承自这个基本表单。我的问题是,它包含几个必须分配的属性,我需要在每个子窗体上验证,如果我已经调用了所有,所以……我想知道是否有一种方法可以自动调用所有这些属性。

控制器代码的一部分:

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();
}

正如你所看到的,方法不是问题,它们是抽象的,所以它们必须被声明(感谢Resharper,如果我错过了一个方法,我将得到警告)。

子表单:

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

我在找这个

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...
}

我不知道我在这里是否愚蠢:/我真的需要摆脱这种怀疑,如果可能的话…那就简化我的工作。

在继承形式中自动实现属性

如果您的目标是确保您的属性初始化为一些默认值,只需向ReportsController添加一个构造函数并在那里设置属性。

现在我明白了,如果你需要强制实现,你应该用抽象属性来实现,继承类应该实现,并且可以用auto-properties来实现:

public abstract class A
{
    public abstract int MyProperty { get; set; }
}
public class B : A
{
    public override int MyProperty { get; set; }
}

简短的回答不是在c# 5.0中,在c# 6.0中你有Auto-Property初始化器,但我认为这不是你要找的。

假设你需要一个无参数的构造函数,你可以创建一个从基构造函数调用的Init抽象方法,并检查你的初始化是否遗漏了一个属性。在这里,您可以抛出异常或显示显示失败的可视消息。

那么在base中你可以这样写:

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();
}

但是也许你必须重新考虑你的设计,并提供一个具有所有属性的单一类,这样你就可以创建一个抽象方法,强制你提供所有这些重要的属性覆盖一个单一的方法:

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();
}

在任何情况下,我更喜欢有一个带参数的基构造函数:

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

然后从构造函数初始化:

 public partial class MyReport:ReportsController
 {
    public MyReport():base(new ComplexProperties { Table="",...})
    {
    }
 }

您可以为抽象基类和子类都需要实现的属性实现一个接口。