在Enum属性中搜索

时间:2013-05-21 10:26:37

标签: c# asp.net enums

我想在Enum中检查传递代码是否存在于任何枚举中。问题是我的枚举定义如下,使用代码属性。

public enum TestEnum
    {

        None,

        [Code("FMNG")]
        FunctionsManagement,

        [Code("INST_MAST_MGT")]
        MasterInstManagement
}

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
    public class CodeAttribute : Attribute
    {
        readonly string _code;
        public string Code
        {
            get
            {
                return _code;
            }
        }
        public CodeAttribute(string code)
        {
            _code = code;
        }
    }

现在,我有可用的字符串(例如“FMNG”),我想在枚举中搜索枚举存在,并且传递的字符串将存在于枚举属性中。

如何使用或传递字符串来检查/获取枚举?我尝试使用Enum.IsDefined(typeof(ActivityEnum), "FMNG")但它没有使用枚举的属性。

5 个答案:

答案 0 :(得分:1)

这是一个通用函数:

    public static object ToEnum(string codeToFind, Type t)
    {
        foreach (var enumValue in Enum.GetValues(t))
        {
            CodeAttribute[] codes = (CodeAttribute[])(enumValue.GetType().GetField(enumValue.ToString()).
            GetCustomAttributes(typeof(CodeAttribute), false));

            if (codes.Length > 0 && codes[0].Code.Equals(codeToFind, StringComparison.InvariantCultureIgnoreCase) ||
                enumValue.ToString().Equals(codeToFind, StringComparison.InvariantCultureIgnoreCase))
                return enumValue;
        }

        return null;
    }

用法:var test = ToEnum("INST_MAST_MGT", typeof(TestEnum));

如果找到定义的Enum属性或Code参数等于Enum的值ToString,则上述函数将返回codeToFind值,您可以根据需要调整它。 / p>

答案 1 :(得分:1)

完全取消该属性并为代码创建静态字典也可能是一个想法:

static Dictionary<string, TestEnum> codeLookup = new Dictionary<string, TestEnum>() { 
                                                     { "FMNG" , TestEnum.FunctionsManagement }, 
                                                     { "INST_MAST_MGT", TestEnum.MasterInsManagement } };

然后就这样做

bool isDefined = codeLookup.ContainsKey("FMNG");

这可能比每次循环属性时使用反射更快,但这取决于您的需求

答案 2 :(得分:0)

public TestEnum GetEnumByAttributeName(string attributeName)
{
    foreach (var item in Enum.GetNames(typeof(TestEnum)))
    {
        var memInfo = typeof(TestEnum).GetMember(item);
        var attributes = memInfo[0].GetCustomAttributes(typeof(CodeAttribute), false);
        if (attributes.Count()> 0 && ((CodeAttribute)attributes[0]).Code == attributeName)
            return (TestEnum)Enum.Parse(typeof(TestEnum), item);
    }
    return TestEnum.None;
}

答案 3 :(得分:0)

您可以使用此方法:

public static T GetEnumValueByAttributeString<T>(string code) where T : struct
{
  if (!typeof(T).IsEnum)
    throw new ArgumentException("T should be an enum");

  var matches = typeof(T).GetFields().Where(f =>
    ((CodeAttribute[])(f.GetCustomAttributes(typeof(CodeAttribute), false))).Any(c => c.Code == code)
    ).ToList();

  if (matches.Count < 1)
    throw new Exception("No match");
  if (matches.Count > 1)
    throw new Exception("More than one match");

  return (T)(matches[0].GetValue(null));
}

就像你看到的那样,它检查你带来的字符串是否含糊不清。像这样使用它:

var testEnum = GetEnumValueByAttributeString<TestEnum>("FMNG");

如果性能问题,您可能需要初始化并保留所有“翻译”的Dictionary<string, T>,以便快速查找。

答案 4 :(得分:0)

我在下面找到了通用方法:

public static T GetEnumValueFromDescription<T>(string description)
        {
            var type = typeof(T);
            if (!type.IsEnum)
                throw new ArgumentException();

            FieldInfo[] fields = type.GetFields();
            var field = fields.SelectMany(f => f.GetCustomAttributes(
                                typeof(CodeAttribute), false), (
                                    f, a) => new { Field = f, Att = a })
                            .Where(a => ((CodeAttribute)a.Att)
                                .Code == description).SingleOrDefault();
            return field == null ? default(T) : (T)field.Field.GetRawConstantValue();
        }

来源:Get Enum from Description attribute