将字符串解析为通用枚举类型

时间:2023-02-05 19:17:17

I'm trying to take some json input and parse into the correct enum type. I have 3 Enum types:

我尝试使用一些json输入并解析成正确的enum类型。我有三种枚举类型:

public class Enums
{
    public enum Motivators{
        Small_Motivator,
        Medium_Motivator,
        Large_Motivator
    }

    public enum Reactors{
        Small_Reactor,
        Large_Reactor
    }         

    public enum Movers{
        Small_Mover,
        Large_Mover
    }
}

I have a method that takes a generic Enum type, and parses to check which type we have.

我有一个方法,它接受一个通用的Enum类型,并解析以检查我们拥有的类型。

    private void InitializeGenerator(Enum enumType)
    {
        if (enumType is Enums.Motivators)
        {
           // work work work work work    
        }
        else if (enumType is Enums.Reactors)
        {
          // work    
        }
        else if (enumType is Enums.Movers)
        {
          // work   
        }
        else
        {
            // we dont know what it is 
        }
    }

My json would look something like this..

我的json看起来是这样的。

{
   "WorkerType":"Small_Motivator"
}

And then trying to parse the json..

然后尝试解析json。

JObject jObject = JObject.Parse(json);
JToken worker = jObject.GetValue("WorkerType");
Enum workerType = (Enum)Enum.Parse((typeof(Enum)), worker.ToString(), true);
InitializeGenerator(workerType); 

throws the following error:

把下面的错误:

An exception of type 'System.ArgumentException' occurred in mscorlib.dll but was not handled in user code

Additional information: Type provided must be an Enum.

4 个解决方案

#1


1  

You can easy parse string to your enum instance. But you should define enum types

您可以轻松地解析字符串到枚举实例。但是您应该定义enum类型。

static void Main(string[] args)
{
    string worker = "Small_Motivator";

    var provider = new EnumProvider();

    var enumValue = provider.GetByValue(worker);
}

public class EnumProvider
{
    public object GetByValue(string sourceStr)
    {
        var enumTypes = new[]
        {
            typeof(Enums.Motivators),
            typeof(Enums.Movers),
            typeof(Enums.Reactors)
        };

        foreach (var type in enumTypes)
        {
            var enumValues = Enum.GetValues(type)
                .Cast<object>()
                .Select(x => x.ToString())
                .ToArray();

            if (enumValues.Any(x => x == sourceStr))
            {
                return Enum.Parse(type, sourceStr);
            }
        }

        throw new ArgumentException($"{sourceStr} not supported");
    }
}

#2


0  

You can't text into an Enum, the base class of every enums. You need to provide a more specific context like Enums.Motivators. But since there is 3 type of enums in your case, you can't use Enum.Parse unless the context is also stored in the json.

不能将文本输入枚举的基类Enum。你需要提供一个更具体的上下文,比如枚举。但是既然你的案例中有三种类型的枚举,你就不能使用Enum。解析,除非上下文也存储在json中。

However, you can generate a dictionary that maps the text to its respective enum value:

但是,您可以生成一个字典,将文本映射到相应的枚举值:

public class Enums
{
    private static readonly IReadOnlyDictionary<string, Enum> mappings = typeof(Enums).GetNestedTypes()
        .Where(x => x.IsEnum)
        .SelectMany(x => x.GetEnumValues().Cast<Enum>())
        .ToDictionary(x => x.ToString(), x => x);

    public static Enum Parse(string value)
    {
        Enum result;
        if (!mappings.TryGetValue(value, out result))
            throw new ArgumentOutOfRangeException("Value: " + value);

        return result;
    }

    // your enum types below...
}

Usage:

用法:

JObject jObject = JObject.Parse(json);
JToken worker = jObject.GetValue("WorkerType");
InitializeGenerator(Enums.Parse(worker.ToString()));

#3


0  

i think here is where you are doing wrong:

我认为这就是你做错的地方:

Motivators workerType = (Motivators) Enum.Parse((typeof(Motivators)), worker.ToString(), true);

now the worker.ToString() must be one of "Small_Motivator" , "Medium_Motivator", "Large_Motivator".

现在,worker.ToString()必须是“small_motivation - ator”、“medium_motivation - ator”、“large_motivation - ator”。

EDIT

编辑

here change your Enums Class to this:

这里把你的课堂换成这个:

public class Enums
{
    public enum Motivators{
     Small_Motivator,
     Medium_Motivator,
     Large_Motivator
    }

    public enum Reactors{
     Small_Reactor,
     Large_Reactor
    }          

    public enum Movers{
     Small_Mover,
     Large_Mover
    }
    public static Enum EnumFactory(string enum_string) {
        if(enum_string.IndexOf("Motivator", StringComparison.OrdinalIgnoreCase) >= 0) {
            return (Motivators) Enum.Parse((typeof(Motivators)), enum_string, true);
        }
        else if(enum_string.IndexOf("Reactor", StringComparison.OrdinalIgnoreCase) >= 0) {
            return (Reactors) Enum.Parse((typeof(Motivators)), enum_string, true);
        }
        else if(enum_string.IndexOf("Mover", StringComparison.OrdinalIgnoreCase) >= 0) {
            return (Movers) Enum.Parse((typeof(Motivators)), enum_string, true);
        }
        return null;
    }
}

you can just call Enums.EnumFactory(worker.ToString()).

您只需调用Enums.EnumFactory(worker.ToString())。


and here is a link for online runtime environment: link

这里有一个在线运行时环境的链接:link

#4


0  

Another option would be to just serialize and deserialize the objects containing the enums using an XmlSerializer or JsonSerializer.

另一种选择是使用XmlSerializer或JsonSerializer对包含枚举的对象进行序列化和反序列化。

#1


1  

You can easy parse string to your enum instance. But you should define enum types

您可以轻松地解析字符串到枚举实例。但是您应该定义enum类型。

static void Main(string[] args)
{
    string worker = "Small_Motivator";

    var provider = new EnumProvider();

    var enumValue = provider.GetByValue(worker);
}

public class EnumProvider
{
    public object GetByValue(string sourceStr)
    {
        var enumTypes = new[]
        {
            typeof(Enums.Motivators),
            typeof(Enums.Movers),
            typeof(Enums.Reactors)
        };

        foreach (var type in enumTypes)
        {
            var enumValues = Enum.GetValues(type)
                .Cast<object>()
                .Select(x => x.ToString())
                .ToArray();

            if (enumValues.Any(x => x == sourceStr))
            {
                return Enum.Parse(type, sourceStr);
            }
        }

        throw new ArgumentException($"{sourceStr} not supported");
    }
}

#2


0  

You can't text into an Enum, the base class of every enums. You need to provide a more specific context like Enums.Motivators. But since there is 3 type of enums in your case, you can't use Enum.Parse unless the context is also stored in the json.

不能将文本输入枚举的基类Enum。你需要提供一个更具体的上下文,比如枚举。但是既然你的案例中有三种类型的枚举,你就不能使用Enum。解析,除非上下文也存储在json中。

However, you can generate a dictionary that maps the text to its respective enum value:

但是,您可以生成一个字典,将文本映射到相应的枚举值:

public class Enums
{
    private static readonly IReadOnlyDictionary<string, Enum> mappings = typeof(Enums).GetNestedTypes()
        .Where(x => x.IsEnum)
        .SelectMany(x => x.GetEnumValues().Cast<Enum>())
        .ToDictionary(x => x.ToString(), x => x);

    public static Enum Parse(string value)
    {
        Enum result;
        if (!mappings.TryGetValue(value, out result))
            throw new ArgumentOutOfRangeException("Value: " + value);

        return result;
    }

    // your enum types below...
}

Usage:

用法:

JObject jObject = JObject.Parse(json);
JToken worker = jObject.GetValue("WorkerType");
InitializeGenerator(Enums.Parse(worker.ToString()));

#3


0  

i think here is where you are doing wrong:

我认为这就是你做错的地方:

Motivators workerType = (Motivators) Enum.Parse((typeof(Motivators)), worker.ToString(), true);

now the worker.ToString() must be one of "Small_Motivator" , "Medium_Motivator", "Large_Motivator".

现在,worker.ToString()必须是“small_motivation - ator”、“medium_motivation - ator”、“large_motivation - ator”。

EDIT

编辑

here change your Enums Class to this:

这里把你的课堂换成这个:

public class Enums
{
    public enum Motivators{
     Small_Motivator,
     Medium_Motivator,
     Large_Motivator
    }

    public enum Reactors{
     Small_Reactor,
     Large_Reactor
    }          

    public enum Movers{
     Small_Mover,
     Large_Mover
    }
    public static Enum EnumFactory(string enum_string) {
        if(enum_string.IndexOf("Motivator", StringComparison.OrdinalIgnoreCase) >= 0) {
            return (Motivators) Enum.Parse((typeof(Motivators)), enum_string, true);
        }
        else if(enum_string.IndexOf("Reactor", StringComparison.OrdinalIgnoreCase) >= 0) {
            return (Reactors) Enum.Parse((typeof(Motivators)), enum_string, true);
        }
        else if(enum_string.IndexOf("Mover", StringComparison.OrdinalIgnoreCase) >= 0) {
            return (Movers) Enum.Parse((typeof(Motivators)), enum_string, true);
        }
        return null;
    }
}

you can just call Enums.EnumFactory(worker.ToString()).

您只需调用Enums.EnumFactory(worker.ToString())。


and here is a link for online runtime environment: link

这里有一个在线运行时环境的链接:link

#4


0  

Another option would be to just serialize and deserialize the objects containing the enums using an XmlSerializer or JsonSerializer.

另一种选择是使用XmlSerializer或JsonSerializer对包含枚举的对象进行序列化和反序列化。