3

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

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”或其他东西),那么组合框绑定将会中断。而且它仍然会编译,所以在加载带有组合框的表单之前没有人会注意到。同样,您将无法使用“查找引用”找到该属性的用途,因为它只是一个字符串。

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

4

3 回答 3

2

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

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

  public static string GetPropName<T>(Expression<Func<T>> propExp)
  {
     return (propExp.Body as MemberExpression).Member.Name;
  }
于 2013-03-07T01:03:00.983 回答
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. 任何未来的开发人员都应该知道,您只能将硬编码的字符串保存在一个地方。所以,他们去常量,看看那里有什么,如果你已经很好地命名了东西,那么任何需要改变的东西对他们来说都应该是显而易见的。
于 2013-03-07T01:12:57.060 回答
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);

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

于 2013-03-07T00:53:54.437 回答