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" などに) リファクタリングすると、コンボボックスのバインドが壊れます。そして、それはまだコンパイルされるので、コンボボックスを含むフォームをロードするまで誰も気付かないでしょう. 同様に、それは単なる文字列であるため、「Find References」を使用してそのプロパティの使用を見つけることはできません。

人々はこれについてどう思いますか?これをどのように使用し、コードを保守可能に保ちますか?

4

3 に答える 3

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;

現在、プロパティ名の自動リファクタリングはまだ役に立ちません。ただし、定数クラスを持つことは2つの良いことを意味します。

  1. 同じ文字列を複数の場所で使用している場合は、ここで1か所で更新するだけで済みます。多くはありません。
  2. 将来の開発者は、ハードコードされた文字列を1か所にのみ保持することを知っておく必要があります。だから、彼らはコンスタンツに行き、そこに何があるかを見て、あなたが物事にうまく名前を付けたなら、変更する必要があるものはすべて彼らに明白であるはずです。
于 2013-03-07T01:12:57.060 に答える
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 に答える
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 に答える