'用户控件'构造函数的参数在C#中

叫我疯了,但我是喜欢带参数的构造函数(如果需要)的人的类型,而不是没有参数的构造函数,然后是设置属性。 我的思想过程:如果需要属性来实际构造对象,则应该在构造函数中进行。 我有两个好处:

  • 我知道当一个对象被构造时(没有错误/异常),我的对象是好的。
  • 它有助于避免忘记设置某个属性。
  • 就形式/用户控制的发展而言,这种思维方式已经开始伤害我。 想象一下这个UserControl

    public partial class MyUserControl : UserControl
    {
      public MyUserControl(int parm1, string parm2)
      {
        // We'll do something with the parms, I promise
        InitializeComponent();
      }
    }
    

    在设计时,如果我将这个UserControl放在窗体上,我会得到一个Exception

    无法创建组件'MyUserControl'...
    System.MissingMethodException - 为此对象定义的无参数构造函数。

    对我来说,唯一的方法就是添加默认的构造函数(除非其他人知道方法)。

    public partial class MyUserControl : UserControl
    {
      public MyUserControl()
      {
        InitializeComponent();
      }
    
      public MyUserControl(int parm1, string parm2)
      {
        // We'll do something with the parms, I promise
        InitializeComponent();
      }
    }
    

    不包括无参数构造函数的重点是避免使用它。 而且我甚至无法使用DesignMode属性来执行类似以下操作:

    public partial class MyUserControl : UserControl
    {
      public MyUserControl()
      {
        if (this.DesignMode)
        {
          InitializeComponent();
          return;
        }
    
        throw new Exception("Use constructor with parameters");
      }
    }
    

    这也不起作用:

    if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
    

    很好,一起移动...

    我有我的无参数构造函数,我可以将它放在窗体上,窗体的InitializeComponent将如下所示:

    private void InitializeComponent()
    {
      this.myControl1 = new MyControl();
    
      // blah, blah
    }
    

    并相信我,因为我这样做了(是的,忽略了Visual Studio生成的注释),我尝试了一下,并将参数传递给InitializeComponent以便我可以将它们传递给MyControl的构造函数。

    这导致我这样做:

    public MyForm()
    {
      InitializeComponent(); // Constructed once with no parameters
    
      // Constructed a second time, what I really want
      this.myControl1 = new MyControl(anInt, aString);  
    }
    

    对于我使用带有参数的UserControl来构造函数,我必须添加一个我不需要的构造函数? 并实例化控件两次?

    我觉得我一定在做错事。 思考? 意见? 保证(希望)?


    有关Windows窗体工作方式的设计决定或多或少地排除了Windows窗体组件的参数化.ctors。 你可以使用它们,但是当你这样做时,你已经走出了通常被批准的机制之外。 相反,Windows窗体倾向于通过属性初始化值。 如果不被广泛使用,这是一种有效的设计技术。

    这虽然有一些好处。

  • 易于使用的客户。 客户端代码不需要追踪一堆数据,它可以立即创建一些东西,只需要合理(如果不感兴趣)的结果就可以看到它。
  • 易于使用的设计师。 设计器代码通常更清晰且更易于解析。
  • 阻止单个组件内的异常数据依赖关系。 (虽然微软也用SplitContainer吹了这个)
  • 在这种技术中,还有很多与设计师合作的形式支持。 诸如DefaultValueAttributeDesignerSerializationVisibilityAttributeBrowsableAttribute使您有机会以最小的努力提供丰富的客户端体验。

    (这不是在Windows窗体中为客户体验做出的唯一折中方案,抽象基类组件也会变得多毛。)

    我建议坚持使用无参数的构造函数,并在Windows窗体设计原则中工作。 如果有真正的先决条件,您的UserControl必须执行,将它们封装到另一个类中,然后通过属性将该类的一个实例分配给您的控件。 这也会让关注点分离得更好一些。


    有两种竞争的设计类的范例:

  • 之后使用无参数的构造函数并设置一堆属性
  • 使用参数化构造函数在构造函数中设置属性
  • Visual Studio Windows窗体设计器强制您在控件上提供无参数构造函数以正常工作。 实际上,它只需要一个无参数的构造函数来实例化控件,而不是设计它们(设计人员在设计控件时会实际解析InitializeComponent方法)。 这意味着您可以使用设计器来设计不带无参数构造函数的窗体或用户控件,但不能设计另一个控件来使用该控件,因为设计器将无法实例化它。

    如果您不打算以编程方式实例化您的控件(即,“手动构建您的UI”),则不必担心创建参数化构造函数,因为它们不会被使用。 即使您要以编程方式实例化您的控件,也可能需要提供无参数的构造函数,以便在需要时仍可在设计器中使用它们。

    无论使用哪种范例,在OnLoad()方法中放入冗长的初始化代码通常也是一个好主意,特别是因为DesignMode属性将在加载时起作用,但在构造函数中不起作用。


    我会推荐

    public partial class MyUserControl : UserControl
    {
        private int _parm1;
        private string _parm2;
    
        private MyUserControl()
        {
            InitializeComponent();
        }
    
        public MyUserControl(int parm1, string parm2) : this()
        {
            _parm1 = parm1;
            _parm2 = parm2;
        }
    }
    

    这样,基础构造函数总是被首先调用,并且任何对组件的引用都是有效的。

    如果需要的话,你可以重载公共控制器,确保控制总是用正确的值进行实例化。

    无论哪种方式,您都确保无参数ctor永远不会被调用。

    我没有测试过,所以如果它跌倒了,我很抱歉!

    链接地址: http://www.djcxy.com/p/61989.html

    上一篇: 'UserControl' constructor with parameters in C#

    下一篇: DomainUpDown (spinner) control is cutting off the bottom pixel of displayed text