c#模式问题

时间:2009-10-03 02:19:58

标签: c# .net

我不知道这篇文章还有什么标题,所以如果你有更好的标题,请随时编辑。


我有两个类:Form和Field。

Form有一个名为Fields的属性,它是一个Field对象列表。

表单有一个名为Prefix的属性。

Field有一个方法需要使用包含它的Form的Prefix属性。

以下是我现在正在做的事情:

class Form
    {
        private List<Field> fields;
        public string Prefix { get; set; }

        public void AddField(Field field)
        {
            field.Form = this;
            fields.Add(field);
        }
    }

    class Field
    {
        public void RenderHtml()
        {
            // render html element with ID attribute
            // prefixed with the parent form's Prefix property
        }
    }

我该怎么做?

8 个答案:

答案 0 :(得分:6)

我会这样做:

class Form
{
    // ...
}

class Field
{
    Form parent;

    public Field(Form parent)
    {
        if (parent == null)
        {
            throw new ArgumentNullException("parent");
        }

        this.parent = parent;
    }

    // now you can reference this.parent to get at its owning form
    // ...
}

答案 1 :(得分:3)

在上面调用Render时,将前缀传递给Field对象。依赖于字段知道其父窗体,以及具有前缀属性的窗体...您正在设置的依赖关系数量可能会变成维护噩梦。

如果你不能在Field.Render上传递前缀,请在Field上有一个property / set方法来传入新的前缀,并在Form上编写setter的自定义实现来设置所有的前缀在表单上设置时包含的字段。

您还可以使用事件做一些事情来获得类似的数据流。

答案 2 :(得分:0)

但说实话,我以前的答案很多:)

Form frm = new Form();
frm.AddField(new Field());    


class Form
        {
            private List<Field> fields;
            public string Prefix { get; set; }
            public string formName;
            public string prefix;

            public void AddField(Field field)
            {
                field.RenderHTML(this.formName,this.prefix);
                fields.Add(field);
            }
        }

        class Field
        {
            public void RenderHTML(string prefix,string id)
            {
                // render html element with ID attribute
                // prefixed with the parent form's Prefix property
            }
        }

OR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Form frm = new Form();
frm.AddField(new Field(frm.formName,frm.prefix));    


class Form
        {
            private List<Field> fields;
            public string Prefix { get; set; }
            public string formName;
            public string prefix;

            public void AddField(Field field)
            {
                field.RenderHTML(this.formName,this.prefix);
                fields.Add(field);
            }
        }

        class Field
        {
            public void Field(string prefix,string id)
            {
                // render html element with ID attribute
                // prefixed with the parent form's Prefix property
            }
        }

答案 3 :(得分:0)

你也可以这样做......

  public class Form
  {        
     private Fields fields = new Fields(this);
     public string Prefix { get; set; }       
     public void AddField(Field field)
     {   
      field.Form = this;
      fields.Add(field);
     }
  }

  public class Fields: List<Field>
  {
      public Form Form { get; set; }
      public Fields(Form form)
      { Form = form; }
      public void Add(Field fleld)
      {
          field.Form = Form;
          Add(field);
      }
  }

答案 4 :(得分:0)

你的方法绝对没有错。 也许我会考虑给Field类提供Prefix属性而不是this引用,但这是一个细节...

答案 5 :(得分:0)

您可以从Collection派生FieldCollection类,并覆盖基类的InsertItem()方法以将父级连接到该字段。

      public class Field 
        { 
              public string Prefix {get;set;}
        }

        public class FieldCollection : System.Collections.ObjectModel.Collection<Field>
        {
              private Form form;

             public FieldCollection(Form f)
             {
                     form = f;
             }


             protected override void InsertItem(int index, Field item)
             {
                     base.InsertItem(index, item);
                     item.Prefix = form.Prefix;
             }
        }

      public class Form
      {
              public string Prefix{get;set;}
              public FieldCollection Fields = new FieldCollection();
      }

答案 6 :(得分:0)

这是一种松散耦合的方式,这样Field就没有对Form的直接了解,而且表单通过使用Field上定义的事件来设置前缀

  public class FieldEventArgs : EventArgs
    {
        public Field Field { get; private set; }
        public FieldEventArgs(Field field)
        {
            Field = field;
        }
    }

    public partial class Field
    {
        public event EventHandler<FieldEventArgs> OnBeforeRender;
        public string Prefix { get;  set; }
         public void Render()
         {
             if (OnBeforeRender != null)
             {
                 OnBeforeRender(this, new FieldEventArgs(this));
                 // render html or do whatever
             }
         }
    }

    public class Form
    {
        private List<Field> Fields;
        public string Prefix { get; set; }

        public void AddField(Field field)
        {
            field.OnBeforeRender += Field_OnBeforeRender;
            Fields.Add(field);
        }

        void Field_OnBeforeRender(object sender, FieldEventArgs e)
        {
            e.Field.Prefix = Prefix;
        }
    }

答案 7 :(得分:0)

一般来说,子对象有四种方式可以获得父对象属性的值,按复杂程度递增的顺序排列:

  1. 在构造中设置子对象中的值。优点:所有出门都很简单。缺点:如果父属性发生变化,则子节点不同步;如果你有很多子对象,可以是内存耗尽,因为每个对象都有自己的值副本。

  2. 保持对父母的引用作为孩子的财产。优点:非常简单;当孩子要求时,属性值是最新的。缺点:如果您将孩子与其父母断开连接,或将其分配给新的孩子,则会出现问题;通常一个好主意是实现一个集合类,其AddRemove方法管理父子关系;由于子对象保留对父对象的引用,因此在没有更多子对象之前不能处理父对象。

  3. 使用事件将属性更改的通知从父级分发给子级。优点:子对象不需要知道有关父进程实现细节的任何信息,或者即使 是父对象,也不需要知道任何内容,缺点:复杂;如果有很多子对象并且父属性经常变化,则表现不佳;初始化儿童财产可能不够优雅;如果子对象没有取消订阅,则不会被处置。

  4. 使用组合(例如数据绑定),以便第三类负责调解父和子之间的更新。优点:极其灵活;一旦你理解了组合基础设施,它就很容易使用 - 这就是为什么WPF有朝一日会征服地球的原因。缺点:具有方法#3的所有缺点,然后一些;如果你没有一个非常非常好的理由(一般来说,你没有),通常太复杂,不值得建立自己的基础设施;使用现有的基础设施(例如WinForms或WPF绑定对象)需要理解和实施相当数量的管道(例如INotifyPropertyChanged或上帝帮助你,依赖属性)。