我知道下面是不可能的,因为枚举的类型必须是int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。
我还有其他选择吗?
我知道下面是不可能的,因为枚举的类型必须是int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。
我还有其他选择吗?
当前回答
这里是扩展方法,我用来获得枚举值作为字符串。首先是枚举。
public enum DatabaseEnvironment
{
[Description("AzamSharpBlogDevDatabase")]
Development = 1,
[Description("AzamSharpBlogQADatabase")]
QualityAssurance = 2,
[Description("AzamSharpBlogTestDatabase")]
Test = 3
}
Description属性来自System.ComponentModel。
这是我的扩展方法:
public static string GetValueAsString(this DatabaseEnvironment environment)
{
// get the field
var field = environment.GetType().GetField(environment.ToString());
var customAttributes = field.GetCustomAttributes(typeof (DescriptionAttribute), false);
if(customAttributes.Length > 0)
{
return (customAttributes[0] as DescriptionAttribute).Description;
}
else
{
return environment.ToString();
}
}
现在,你可以使用下面的代码访问枚举字符串值:
[TestFixture]
public class when_getting_value_of_enum
{
[Test]
public void should_get_the_value_as_string()
{
Assert.AreEqual("AzamSharpBlogTestDatabase",DatabaseEnvironment.Test.GetValueAsString());
}
}
其他回答
. net Core 3.0/ c# 8.0(如果你的工作环境允许你升级你的项目)新增了一个简短的switch语句,看起来有点枚举。在一天结束的时候,这和我们多年来一直在使用的无聊的开关语句是一样的。
这里唯一真正的区别是switch语句得到了一个新的suit。
public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};
你会注意到上面我从这里复制的代码,实际上是使用一个枚举作为参数。
这并不是您想要的(相信我,我早就想要类似OP要求的东西了),但我实际上觉得这是MS. JMO抛出的橄榄枝。
希望它能帮助到一些人!
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; }
}
}
我做过类似的事情;
public enum BusinessUnits
{
NEW_EQUIPMENT = 0,
USED_EQUIPMENT = 1,
RENTAL_EQUIPMENT = 2,
PARTS = 3,
SERVICE = 4,
OPERATOR_TRAINING = 5
}
public class BusinessUnitService
{
public static string StringBusinessUnits(BusinessUnits BU)
{
switch (BU)
{
case BusinessUnits.NEW_EQUIPMENT: return "NEW EQUIPMENT";
case BusinessUnits.USED_EQUIPMENT: return "USED EQUIPMENT";
case BusinessUnits.RENTAL_EQUIPMENT: return "RENTAL EQUIPMENT";
case BusinessUnits.PARTS: return "PARTS";
case BusinessUnits.SERVICE: return "SERVICE";
case BusinessUnits.OPERATOR_TRAINING: return "OPERATOR TRAINING";
default: return String.Empty;
}
}
}
用这个称呼它;
BusinessUnitService.StringBusinessUnits(BusinessUnits.PARTS)
可以向枚举中的项添加属性,然后使用反射从属性中获取值。
你必须使用"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本身,以便您能够确定是否应用了该属性。
Glennular Extension方法的一个小调整,所以你可以在其他东西上使用扩展,而不仅仅是ENUM的;
using System;
using System.ComponentModel;
namespace Extensions {
public static class T_Extensions {
/// <summary>
/// Gets the Description Attribute Value
/// </summary>
/// <typeparam name="T">Entity Type</typeparam>
/// <param name="val">Variable</param>
/// <returns>The value of the Description Attribute or an Empty String</returns>
public static string Description<T>(this T t) {
DescriptionAttribute[] attributes = (DescriptionAttribute[])t.GetType().GetField(t.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : string.Empty;
}
}
}
或者使用Linq
using System;
using System.ComponentModel;
using System.Linq;
namespace Extensions {
public static class T_Extensions {
public static string Description<T>(this T t) =>
((DescriptionAttribute[])t
?.GetType()
?.GetField(t?.ToString())
?.GetCustomAttributes(typeof(DescriptionAttribute), false))
?.Select(a => a?.Description)
?.FirstOrDefault()
?? string.Empty;
}
}