2

LinqToSql を使用してテーブルに列挙値をマッピングする方法について以前質問したところ、O/R デザイナーを使用して型を global::MyNamespace.TMyEnum に設定するという回答がありました。

列挙が整数に基づいている場合、それは問題なく機能します。しかし、列挙型が文字列値に基づいている場合はどうでしょうか? これの最も明白なアプリケーションは次のとおりです。

public enum TGender {
  Male,
  Female,
  Unknown,
}

ここで、データベース上の同等の値はMFおよびUです。列挙型を文字列として入力することはできません。ではGender、LinqToSql オブジェクトのプロパティがTGender値を返すようにするにはどうすればよいでしょうか?

4

2 に答える 2

4

次のようなゲッター プロパティを LINQ to SQL オブジェクトに追加します。

public TGender Gender
{
   switch(this.DbGender)
   {
      case "M":
        return TGender.Male;
   }
}

または、巨大な switch ステートメントを使用したくない場合は、その値のデータベース内の文字列値を表す文字列プロパティを持つ属性を列挙型に追加できます。次に、リフレクションを使用して正しい列挙型を取得し、それを返します。

リフレクションと属性を使用してそれを行うサンプルを次に示します。

public class EnumAttribute : Attribute
{
    public string DbValue
    {
        get;
        set;
    }
}

public enum TGender
{
    [EnumAttribute(DbValue = "M")]
    Male,
    [EnumAttribute(DbValue = "F")]
    Female,
    [EnumAttribute(DbValue = "U")]
    Unknown
}

    public TGender GetEnumValue(string s)
    {
        foreach (TGender item in Enum.GetValues(typeof(TGender)))
        {
            FieldInfo info = typeof(TGender).GetField(item.ToString());
            var attribs = info.GetCustomAttributes(typeof(EnumAttribute), false);
            if (attribs.Length > 0)
            {
                EnumAttribute a = attribs[0] as EnumAttribute;
                if (s == a.DbValue)
                {
                    return item;
                }
            }
        }

        throw new ArgumentException("Invalid string value.");
    }

テストするには:

var item = GetEnumValue("M");
Console.WriteLine(item);

これにより、「男性」が得られます。

于 2009-06-23T16:05:38.230 に答える
1

列挙型の代わりに動作クラスのルートに進むことを提案させてください。switch ステートメントを完全に排除し、アイテムごとにメタ データと動作を関連付けることができます。

public class Gender
{
    private static readonly Dictionary<string, Gender> _items = new Dictionary<string, Gender>();

    public static readonly Gender Male = new Gender("M", "he", age => age >= 14);
    public static readonly Gender Female = new Gender("F", "she", age => age >= 13);
    public static readonly Gender Unknown = new Gender("U", "he/she", age => null);

    public string DatabaseKey { get; private set; }
    public string Pronoun { get; private set; }
    public Func<int, bool?> CanGetMarriedInTexas { get; set; }

    private Gender(string databaseKey, string pronoun, Func<int,bool?> canGetMarriedInTexas)
    {
        DatabaseKey = databaseKey;
        Pronoun = pronoun;
        CanGetMarriedInTexas = canGetMarriedInTexas;
        _items.Add(databaseKey, this);
    }

    public static Gender GetForDatabaseKey(string databaseKey)
    {
        if (databaseKey == null)
        {
            return Unknown;
        }
        Gender gender;
        if (!_items.TryGetValue(databaseKey, out gender))
        {
            return Unknown;
        }
        return gender;
    }

    public IEnumerable<Gender> All()
    {
        return _items.Values;
    }
}

スイッチを使用してデータベース キーを取得する代わりに、次のように要求します。

public void MapViewToPerson(IEditPersonInfoView view, Person person)
{
    person.Gender = view.Gender.DatabaseKey;
    // ...
}

必要な情報を Gender オブジェクトに尋ねるだけで、性別固有の動作を適用することもできます。たとえば、テキサス州の法定婚姻年齢は性別によって異なります。

public void MapPersonToView(IEditPersonInfoView view, Person person)
{
    Gender gender = Gender.GetForDatabaseKey(person.Gender);
    view.Gender = gender;
    view.ShowMarriageSection = gender.CanGetMarriedInTexas(person.AgeInYears) ?? true;
    // ...
}
于 2009-06-23T18:01:42.297 に答える