数据绑定和重构代码

时间:2013-03-07 00:15:28

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

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

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";

这就是我理解它应该至少完成的方式。我看到了我在网上找到的所有解释的实现。

但是将显示和值成员作为变量名称的硬编码字符串似乎让我感到不安。 如果有人在Visual Studio中出现多年并重构ObjectID属性(成为“MyID”或其他东西),则组合框绑定会中断。它仍然会编译,因此在加载带有组合框的表单之前,没有人会注意到。 同样,您将无法使用“查找引用”找到该属性的用法,因为它只是一个字符串。

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

3 个答案:

答案 0 :(得分:2)

可以在没有传递成员类型的情况下完成吗?

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

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

答案 1 :(得分: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. 任何未来的开发人员都应该知道您只能将硬编码字符串保存在一个位置。所以,他们去常数,看看那里有什么,如果你已经很好地命名,那么任何需要改变的东西对他们来说应该是显而易见的。

答案 2 :(得分:1)

在仍然强类型的情况下获取属性名称的方法可能是使用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);

缺点是你必须传入对象类型和成员类型,但是编译器应该为你捕获这个。这应该也可以通过自动重构来处理。