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对包含枚举的对象进行序列化和反序列化。