2009-06-23 78 views
2

我问了一个previous question关于使用LinqToSql映射表上的枚举值,答案是使用O/R设计器将类型设置为global :: MyNamespace.TMyEnum。如何使用LinqToSql将字符串值隐式转换为枚举?

如果您的枚举基于整数,那么工作正常。但是,如果你的枚举基于字符串值呢?这方面最明显的应用是:

public enum TGender { 
    Male, 
    Female, 
    Unknown, 
} 

在数据库中的相应值是MFU。您无法将枚举类型输入为字符串,那么如何让LinqToSql对象的Gender属性返回TGender值?

回答

4

我一个getter属性,以我的LINQ添加到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); 

这会导致 “男性”。

+0

好的......但你如何让Linq自动投出“M”给TGender.Male,“F”给TGender.Female等?我不想为“DbGender”(字符串)和“性别”(TGender)分别设置属性 - 字符串属性根本没有用处,我也不想用不必要的接口来污染我的代码。 – 2009-06-23 16:26:11

1

允许我建议走行为类的路线而不是枚举。您将完全消除开关语句,并有能力逐项关联元数据和行为。

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; 
    // ... 
} 

您还可以通过简单地问自己希望得到的信息的性别对象应用于特定性别的行为。例如,得克萨斯州的合法结婚年龄与性别有关。

public void MapPersonToView(IEditPersonInfoView view, Person person) 
{ 
    Gender gender = Gender.GetForDatabaseKey(person.Gender); 
    view.Gender = gender; 
    view.ShowMarriageSection = gender.CanGetMarriedInTexas(person.AgeInYears) ?? true; 
    // ... 
}