【问题标题】:Databinding and refactoring code [closed]数据绑定和重构代码 [关闭]
【发布时间】:2013-03-07 00:15:28
【问题描述】:

我只是对将数据绑定到组合框(或我猜的其他可绑定对象)背后的一些编码实践感到好奇。 假设我创建了一个对象,我想将它们添加到组合框中。 所以我创建了我的对象并给它一些属性。

public class ObjectForList
{
    public string ObjectName { get; set; }
    public int ObjectID { get; set; }
    public string SomeOtherProperty { get; set; }
    public ObjectForList()
    {
    }
}

然后我列出它们并将其设置为我的组合框的来源

List<ObjectForList> myObjects= new List<ObjectForList> { ...bunch of ObjectForList objects...};

comboBox1.DataSource = myObjects;
comboBox1.DisplayMember = "ObjectName";
comboBox1.ValueMember = "ObjectID";

我是这么理解的,至少应该这样做。我在网上找到的所有解释中都看到了该实现。

但是,将 Display 和 Value 成员作为变量名称的硬编码字符串对我来说似乎并不容易。 如果几年后有人在 Visual Studio 中出现并重构 ObjectID 属性(为“MyID”或其他东西),那么组合框绑定将会中断。而且它仍然会编译,所以在加载带有组合框的表单之前没有人会注意到。 同样,您将无法使用“查找引用”找到该属性的用途,因为它只是一个字符串。

人们对此有何看法?如何使用它并保持代码可维护?

【问题讨论】:

  • 你是绝对正确的。 VS 的自动重构不会处理这个问题,如果你有很多 ComboBox,它可能会有点麻烦。据我所知,没有很好的方法来解决这个问题......
  • 好问题,OP。以亚当的评论和您的帖子为基础,有谁知道 Resharper 是否可以处理这样的案件?
  • 每小时去一次酒类商店,因为这个难题是一个很好的问题。
  • ReSharper 将告诉您正在重命名的符号的任何字符串用法,并提供为您更改它。有时这非常有用,就像您在此处的示例一样。

标签: c# .net data-binding visual-studio-2005


【解决方案1】:

也可以在不传递成员类型的情况下完成,对吗?

  comboBox1.ValueMember = GetPropName(() => ObjectForListObject.ObjectID);

  public static string GetPropName<T>(Expression<Func<T>> propExp)
  {
     return (propExp.Body as MemberExpression).Member.Name;
  }

【讨论】:

    【解决方案2】:

    使用常量。就我而言,我将所有这些硬编码的字符串放入一个单独的类中,如下所示:

    public static class Constants
    {
        public static class MyObjects
        {
            public const string DisplayMember = "ObjectName";
            public const string ValueMember = "ObjectID";
        }
    }
    

    这样使用:

    comboBox1.DataSource = myObjects;
    comboBox1.DisplayMember = Constants.MyObjects.DisplayMember;
    comboBox1.ValueMember = Constants.MyObjects.ValueMember;
    

    现在,属性名称的自动重构仍然没有帮助。然而,拥有一个常量类确实意味着两件好事:

    1. 如果你在多个地方使用相同的字符串,那么你只需要在一个地方更新它..不多
    2. 任何未来的开发人员都应该知道,您只能将硬编码字符串保存在一个地方。所以,他们会去常量,看看那里有什么,如果你已经很好地命名了,那么任何需要改变的东西对他们来说都应该是显而易见的。

    【讨论】:

      【解决方案3】:

      在仍然是强类型的同时获取属性名称的一种方法可能是使用 linq 表达式。在您的示例中,它可能类似于以下内容:

      Expression<Func<ObjectForList, String>> exp = o => o.ObjectName;
      MemberExpression member = (MemberExpression)exp.Body;
      comboBox1.DisplayMember = member.Member.Name;
      

      当然,您可能希望将其封装为一种方法,这样您就不必每次都按照这些方式重新编写一些东西。

      class Tools
      {
          public static String GetMemberName<ObjType, MemberType>(Expression<Func<ObjType, MemberType>> expression)
          {
              MemberExpression member = (MemberExpression)expression.Body;
              return member.Member.Name;
          }
      }
      

      那么你就可以使用

      List<ObjectForList> myObjects= new List<ObjectForList> { ...bunch of ObjectForList objects...};
      
      comboBox1.DataSource = myObjects;
      comboBox1.DisplayMember = Tools.GetMemberName<ObjectForList, String>(o => o.Objectname);
      comboBox1.ValueMember = Tools.GetMemberName<ObjectForList, int>(o => o.ObjectID);
      

      缺点是您必须同时传递对象类型和成员类型,但是编译器应该会为您捕捉到这一点。这应该也可以通过自动重构来处理。

      【讨论】:

        猜你喜欢
        • 2010-11-03
        • 1970-01-01
        • 2016-05-12
        • 2017-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-05
        • 1970-01-01
        相关资源
        最近更新 更多