我知道下面是不可能的,因为枚举的类型必须是int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。
我还有其他选择吗?
我知道下面是不可能的,因为枚举的类型必须是int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。
我还有其他选择吗?
当前回答
我会把它变成一个类,完全避免使用枚举。然后使用类型处理程序,你可以在从db中获取对象时创建对象。
即:
public class Group
{
public string Value{ get; set; }
public Group( string value ){ Value = value; }
public static Group TheGroup() { return new Group("OEM"); }
public static Group OtherGroup() { return new Group("CMB"); }
}
其他回答
我的第一个问题-你有访问数据库本身的权限吗?这应该在数据库中规范化,否则,任何解决方案都将容易出错。根据我的经验,充满“OEM”和“CMB”的数据字段往往会随着时间的推移混合“OEM”和其他“垃圾数据”....如果可以规范化它,就可以使用包含元素的表中的键作为Enum,这样就完成了,结构更加简洁。
如果这是不可用的,我将使你的Enum,并使一个类来解析你的字符串为你的Enum。这至少会让您在处理非标准条目时具有一定的灵活性,在捕获或处理错误时也比使用enumeration . parse /Reflection/etc等方法灵活得多。字典可以工作,但如果你遇到大小写问题,可能会崩溃。
我建议你写一个类,这样你就可以:
// I renamed this to GroupType, since it sounds like each element has a single type...
GroupType theType = GroupTypeParser.GetGroupType(theDBString);
这样可以保留大部分的可读性,而不必更改DB。
public class DataType
{
private readonly string value;
private static readonly Dictionary<string, DataType> predefinedValues;
public static readonly DataType Json = new DataType("json");
public static readonly DataType Xml = new DataType("xml");
public static readonly DataType Text = new DataType("text");
public static readonly DataType Html = new DataType("html");
public static readonly DataType Binary = new DataType("binary");
static DataType()
{
predefinedValues = new Dictionary<string, DataType>();
predefinedValues.Add(Json.Value, Json);
predefinedValues.Add(Xml.Value, Xml);
predefinedValues.Add(Text.Value, Text);
predefinedValues.Add(Html.Value, Html);
predefinedValues.Add(Binary.Value, Binary);
}
private DataType(string value)
{
this.value = value;
}
public static DataType Parse(string value)
{
var exception = new FormatException($"Invalid value for type {nameof(DataType)}");
if (string.IsNullOrEmpty(value))
throw exception;
string key = value.ToLower();
if (!predefinedValues.ContainsKey(key))
throw exception;
return predefinedValues[key];
}
public string Value
{
get { return value; }
}
}
可以向枚举中的项添加属性,然后使用反射从属性中获取值。
你必须使用"field"说明符来应用属性,如下所示:
enum GroupTypes
{
[field:Description("OEM")]
TheGroup,
[field:Description("CMB")]
TheOtherGroup
}
然后你将反射枚举类型的静态字段(在本例中是GroupTypes),并使用反射获取你正在寻找的值的DescriptionAttribute:
public static DescriptionAttribute GetEnumDescriptionAttribute<T>(
this T value) where T : struct
{
// The type of the enum, it will be reused.
Type type = typeof(T);
// If T is not an enum, get out.
if (!type.IsEnum)
throw new InvalidOperationException(
"The type parameter T must be an enum type.");
// If the value isn't defined throw an exception.
if (!Enum.IsDefined(type, value))
throw new InvalidEnumArgumentException(
"value", Convert.ToInt32(value), type);
// Get the static field for the value.
FieldInfo fi = type.GetField(value.ToString(),
BindingFlags.Static | BindingFlags.Public);
// Get the description attribute, if there is one.
return fi.GetCustomAttributes(typeof(DescriptionAttribute), true).
Cast<DescriptionAttribute>().SingleOrDefault();
}
我选择在上面返回DescriptionAttribute本身,以便您能够确定是否应用了该属性。
使用类。
编辑:更好的例子
class StarshipType
{
private string _Name;
private static List<StarshipType> _StarshipTypes = new List<StarshipType>();
public static readonly StarshipType Ultralight = new StarshipType("Ultralight");
public static readonly StarshipType Light = new StarshipType("Light");
public static readonly StarshipType Mediumweight = new StarshipType("Mediumweight");
public static readonly StarshipType Heavy = new StarshipType("Heavy");
public static readonly StarshipType Superheavy = new StarshipType("Superheavy");
public string Name
{
get { return _Name; }
private set { _Name = value; }
}
public static IList<StarshipType> StarshipTypes
{
get { return _StarshipTypes; }
}
private StarshipType(string name, int systemRatio)
{
Name = name;
_StarshipTypes.Add(this);
}
public static StarshipType Parse(string toParse)
{
foreach (StarshipType s in StarshipTypes)
{
if (toParse == s.Name)
return s;
}
throw new FormatException("Could not parse string.");
}
}
您可以使用两个枚举。一个用于数据库,另一个用于可读性。
你只需要确保它们保持同步,这似乎是一个小成本。 你不必设置值,只是设置相同的位置,但设置值可以非常清楚地表明两个枚举是相关的,并防止错误重新排列枚举成员。注释让维护人员知道这些是相关的,必须保持同步。
// keep in sync with GroupTypes
public enum GroupTypeCodes
{
OEM,
CMB
}
// keep in sync with GroupTypesCodes
public enum GroupTypes
{
TheGroup = GroupTypeCodes.OEM,
TheOtherGroup = GroupTypeCodes.CMB
}
要使用它,你只需要先转换为代码:
GroupTypes myGroupType = GroupTypes.TheGroup;
string valueToSaveIntoDatabase = ((GroupTypeCodes)myGroupType).ToString();
然后,如果你想让它更方便,你可以添加一个扩展函数,只适用于这种类型的枚举:
public static string ToString(this GroupTypes source)
{
return ((GroupTypeCodes)source).ToString();
}
然后你可以这样做:
GroupTypes myGroupType = GroupTypes.TheGroup;
string valueToSaveIntoDatabase = myGroupType.ToString();