我知道下面是不可能的,因为枚举的类型必须是int

enum GroupTypes
{
    TheGroup = "OEM",
    TheOtherGroup = "CMB"
}

从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。

我还有其他选择吗?


当前回答

我不需要任何健壮的东西,比如将字符串存储在属性中。我只需要转动MyEnum之类的东西。BillEveryWeek变成“每周账单”或MyEnum。将elegacysystem转换为“使用遗留系统”——基本上通过驼峰式大小写将枚举拆分为单个小写单词。

public static string UnCamelCase(this Enum input, string delimiter = " ", bool preserveCasing = false)
{
    var characters = input.ToString().Select((x, i) =>
    {

       if (i > 0 && char.IsUpper(x))
       {
           return delimiter + x.ToString(CultureInfo.InvariantCulture);
       }
       return x.ToString(CultureInfo.InvariantCulture);

    });

    var result = preserveCasing
       ? string.Concat(characters)
       : string.Concat(characters).ToLower();

    var lastComma = result.LastIndexOf(", ", StringComparison.Ordinal);

    if (lastComma > -1)
    {
       result = result.Remove(lastComma, 2).Insert(lastComma, " and ");
    }

    return result;
}

myenume . uselegacysystem . uncamelcase()输出"使用遗留系统"

如果设置了多个标志,它会将其转换为普通英语(逗号分隔,除了最后一个逗号中的“and”)。

var myCustomerBehaviour = MyEnum.BillEveryWeek | MyEnum.UseLegacySystem | MyEnum.ChargeTaxes;

Console.WriteLine(myCustomerBehaviour.UnCamelCase());
//outputs "bill every week, use legacy system and charge taxes"

其他回答

我喜欢在类中使用属性而不是方法,因为它们看起来更像枚举。

下面是一个Logger的例子:

public class LogCategory
{
    private LogCategory(string value) { Value = value; }

    public string Value { get; private set; }

    public static LogCategory Trace   { get { return new LogCategory("Trace"); } }
    public static LogCategory Debug   { get { return new LogCategory("Debug"); } }
    public static LogCategory Info    { get { return new LogCategory("Info"); } }
    public static LogCategory Warning { get { return new LogCategory("Warning"); } }
    public static LogCategory Error   { get { return new LogCategory("Error"); } }

    public override string ToString()
    {
        return Value;
    }
}

传入类型安全的字符串值作为参数:

public static void Write(string message, LogCategory logCategory)
{
    var log = new LogEntry { Message = message };
    Logger.Write(log, logCategory.Value);
}

用法:

Logger.Write("This is almost like an enum.", LogCategory.Info);

我的第一个问题-你有访问数据库本身的权限吗?这应该在数据库中规范化,否则,任何解决方案都将容易出错。根据我的经验,充满“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。

我基本上是在寻找@ArthurC的反思答案

稍微扩展一下他的回答,你可以通过一个泛型函数来让它更好:

    // If you want for a specific Enum
    private static string EnumStringValue(GroupTypes e)
    {
        return EnumStringValue<GroupTypes>(e);
    }

    // Generic
    private static string EnumStringValue<T>(T enumInstance)
    {
        return Enum.GetName(typeof(T), enumInstance);
    } 

然后你就可以把你有的东西都包起来了

EnumStringValue(GroupTypes.TheGroup) // if you incorporate the top part

or

EnumStringValue<GroupTypes>(GroupTypes.TheGroup) // if you just use the generic

尝试向静态类中添加常量。你最终不会得到一个Type,但你会得到可读的、有组织的常量:

public static class GroupTypes {

    public const string TheGroup = "OEM";
    public const string TheOtherGroup = "CMB";

}

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