2

そのため、データベースからいくつかの情報を引き出しており、それをモデルのプロパティにマップする必要があります。これに対する私の最初の試みでは、明らかなパターンに従っている大きな switch ステートメントが生成されました。この脆弱なコードをより動的な方法で表現できないかと考えています。

foreach (AttributeValue attributeValue in attributeValues)
{
    string label = attributes.First(a => a.ID == attributeValue.AttributeID).Name;
    switch (attributeValue.AttributeName)
    {
        case "TaskSequence":
            TaskSequenceLabel = label;
            break;
        case "TaskStatus":
            TaskStatusLabel = label;
            break;
        case "InstallChangeNumber":
            InstallChangeNumberLabel = label;
            break;
        case "InstallChangeStart":
            InstallChangeStartLabel = label;
            break;
        case "InstallChangeEnd":
            InstallChangeEndLabel = label;
            break;
        case "SubmittedDateTime":
            SubmittedDateTimeLabel = label;
            break;
        case "InstalledDateTime":
            InstalledDateTimeLabel = label;
            break;
    }
}

基本的に私が考えているのは、「ラベルの値+「ラベル」を持つプロパティにラベルをマップする」ことです

4

3 に答える 3

2

ラベルを辞書に保存し、それぞれのキーを使用して必要なラベルを取得できます。これは、戦略パターンの非常に単純な実装と見なすことができます。

var labels = new Dictionary<string, Label>();
labels.Add("TaskSequence", TaskSequenceLabel);
labels.Add("TaskStatus", TaskStatusLabel);
// etc.

attributeValues.ForEach(value => {
    string label = attributes.First(a => a.ID == value.AttributeID).Name;
    labels[value.AttributeName] = label;
});

複数の場所で必要な場合は、独自のクラスにリファクタリングできます。

public class MyLabels
{
    public Dictionary<string, Label> _labels =
                  new Dictionary<string< Label>();

    public MyLabels() {
        _labels.Add("TaskSequence", TaskSequenceLabel);
        _labels.Add("TaskStatus", TaskStatusLabel);
        // etc.
    }

    public Label Named(string name) {
        return _labels[name];
    }
}

// Usage:
var labels = new MyLabels();
attributeValues.ForEach(value => {
    string label = attributes.First(a => a.ID == value.AttributeID).Name;
    labels.Named(value.AttributeName) = label;
});
于 2012-11-15T21:50:20.720 に答える
2

もちろん、リフレクションのみのソリューションでうまくいきます。

ただし、関心のあるメンバーを装飾できるカスタム属性の使用を評価します。現在オンにしている属性名を指定するために使用できるもの。

TaskSequence->TaskSequenceLabelコンベンションベースのマッピングとは無関係であるため、リフレクションのみを使用するよりも堅牢なソリューションのように見えます。

リフレクションのみのアプローチでは、誰かが の名前を変更した場合、TaskSequence機能しなくなった理由を突き止めることが必要以上に困難になる可能性があります。ただし、属性がある場合は、気にする必要はありません。もちろん、データベース内のフィールドの名前が変更された場合は気にします

編集

明確にするためにいくつかのコードを追加させてください (実際には疑似コードです。ここには Visual Studio のコピーはありません)。入力したいプロパティだと思います。

// here's the custom attribute. Ok, should probably be sealed and bla bla bla.

public class MapToAttribute : Attribute {
  readonly string _fieldName;

  public MapToAttribute(string fieldName) {
    _fieldName = fieldName;
  }
}

// here's your model
public class SomeModel {
  [MapTo("TaskSequence")]
  public int TaskSequence { get; set; }
}

// here's how you figure out which property have the MapTo attribute
from p in typeof(SomeModel).GetProperties() where p.IsDefined(typeof(MapToAttribute))

残りは読者の演習として残します。PropertyInfo.SetValueと友達。

于 2012-11-15T21:50:48.473 に答える
2

リフレクションでそれを行うことができます:

foreach (AttributeValue attributeValue in attributeValues)
{
    string label = attributes.First(a => a.ID == attributeValue.AttributeID).Name;
    string propertyName = attributeValue.AttributeName + "Label";
    PropertyInfo pi = GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
    // check for null, if it is possible that property not exists
    pi.SetValue(this, label, null);
}
于 2012-11-15T21:42:51.867 に答える