自定义枚举解析 [英] Custom Enum Parse

查看:104
本文介绍了自定义枚举解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举如下:

  public enum MyEnum {One,Two,Three} 

我想将一些字符串放在上面的枚举上,例如,下面的字符串将被解析为MyEnum.Two:

 Two,TWO,Second,2

我知道我可以维护一个映射函数来完成这项工作。但是,我只想找一个更好的方法,例如,重写Enum.Parse函数,或类似的东西。我试图使用IConvertable,但似乎不可能。任何想法?

解决方案

  [AttributeUsage(AttributeTargets.Field,AllowMultiple = true)] 
public class NameAttribute:Attribute
{
public readonly string [] Names;

public NameAttribute(string name)
{
if(name == null)
{
throw new ArgumentNullException();
}

Names = new [] {name};
}

public NameAttribute(params string [] names)
{
if(names == null || names.Any(x => x == null))
{
throw new ArgumentNullException();
}

Names = names;
}
}

public static class ParseEnum
{
public static TEnum Parse< TEnum>(string value)其中TEnum:struct
{
return ParseEnumImpl< TEnum> .Values [value];
}

public static bool TryParse< TEnum>(string value,out TEnum result)其中TEnum:struct
{
返回ParseEnumImpl< TEnum> .Values.TryGetValue (值,输出结果);
}

private static class ParseEnumImpl< TEnum>其中TEnum:struct
{
public static readonly Dictionary< string,TEnum> Values = new Dictionary< string,TEnum>();

static ParseEnumImpl()
{
var nameAttributes = typeof(TEnum)
.GetFields()
.Select(x => new
{
Value = x,
Names = x.GetCustomAttributes(typeof(NameAttribute),false)
.Cast< NameAttribute>()
});

var degrouped = nameAttributes.SelectMany(
x => x.Names.SelectMany(y => y.Names),
(x,y)=> new {Value = x.Value,Name = y});

值= degrouped.ToDictionary(
x => x.Name,
x =>(TEnum)x.Value.GetValue(null));
}
}
}

然后你可以(注意 [Name] ,多个 [Name] 或单个 [Name] 具有多个名称):

  public enum TestEnum 
{
[Name( 1)]
[名称(Foo)]
[名称(F)]
[名称(XF,YF)]
Foo = 1,

[名称(2)]
[名称(酒吧)]
[名称(B)]
[名称( XB,YB)]
Bar = 2
}

  TestEnum r1 = ParseEnum.Parse< TestEnum>(XF); 
TestEnum r2;
bool r3 = ParseEnum.TryParse< TestEnum>(YB,out r2);注意使用内部类( ParseEnumImpl< TEnum> )缓存 TEnum 名称。


I have an enum as below:

public enum MyEnum {  One,  Two,  Three}

And I would like to pare some strings to above enum, for example, below strings are going to be parsed as MyEnum.Two:

"Two", "TWO", "Second", "2"

I know I can maintain a mapping function to do this job. However, I just want to find a better way, for example, override Enum.Parse function, or something like that. I have tried to use IConvertable, but it seems not possible. Any idea?

解决方案

[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
public class NameAttribute : Attribute
{
    public readonly string[] Names;

    public NameAttribute(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException();
        }

        Names = new[] { name };
    }

    public NameAttribute(params string[] names)
    {
        if (names == null || names.Any(x => x == null))
        {
            throw new ArgumentNullException();
        }

        Names = names;
    }
}

public static class ParseEnum
{
    public static TEnum Parse<TEnum>(string value) where TEnum : struct
    {
        return ParseEnumImpl<TEnum>.Values[value];
    }

    public static bool TryParse<TEnum>(string value, out TEnum result) where TEnum : struct
    {
        return ParseEnumImpl<TEnum>.Values.TryGetValue(value, out result);
    }

    private static class ParseEnumImpl<TEnum> where TEnum : struct
    {
        public static readonly Dictionary<string, TEnum> Values = new Dictionary<string,TEnum>();

        static ParseEnumImpl()
        {
            var nameAttributes = typeof(TEnum)
                .GetFields()
                .Select(x => new 
                { 
                    Value = x, 
                    Names = x.GetCustomAttributes(typeof(NameAttribute), false)
                        .Cast<NameAttribute>() 
                });

            var degrouped = nameAttributes.SelectMany(
                x => x.Names.SelectMany(y => y.Names), 
                (x, y) => new { Value = x.Value, Name = y });

            Values = degrouped.ToDictionary(
                x => x.Name, 
                x => (TEnum)x.Value.GetValue(null));
        }
    }
}

Then you can (note the double syntax for [Name], multiple [Name] or single [Name] with multiple names):

public enum TestEnum
{
    [Name("1")]
    [Name("Foo")]
    [Name("F")]
    [Name("XF", "YF")]
    Foo = 1,

    [Name("2")]
    [Name("Bar")]
    [Name("B")]
    [Name("XB", "YB")]
    Bar = 2
}

and

TestEnum r1 = ParseEnum.Parse<TestEnum>("XF");
TestEnum r2;
bool r3 = ParseEnum.TryParse<TestEnum>("YB", out r2);

Note the use of an inner class (ParseEnumImpl<TEnum>) to cache the TEnum "names".

这篇关于自定义枚举解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆