我有一个读取一些XML并填充对象的方法。这是通过基于XML对象的属性名称中的元素名称的反射来完成的。这适用于基本对象类型,但我正在努力使用枚举数组。
所以我有一个PropertyInfo对象(让我们调用它属性)为我的枚举数组属性,我有一个字符串值(让我们称之为值)包含表示枚举值的逗号分隔数字(例如“1,3,5”)
我试过了:
property.SetValue(this, value.Split(',').Select(i => int.Parse(i)).ToArray(), null);
和
property.SetValue(this, value.Split(',').Select(i => Enum.ToObject(property.PropertyType.GetElementType(), int.Parse(i))).ToArray(), null);
但没有快乐。在第一个代码示例中,Select.ToArray的结果是一个int [],然后抛出一个解析错误。类似于第二种情况,但Select.ToArray返回一个对象[]并再次抛出一个解析错误。
我想写这个就像枚举类型未知一样。
有什么想法吗?
答案 0 :(得分:2)
试试这个:
// create the enum values as object[]
var values = value.Split(',')
.Select(i => Enum.Parse(property.PropertyType.GetElementType(), i))
.ToArray()
// create array of correct type
Array array = (Array)Activator.CreateInstance(property.PropertyType, values.Length);
// copy the object values to the array
int i = 0;
foreach(var value in values)
{
array.SetValue(value, i++);
}
// set the property
property.SetValue(this, array, null)
可能有一种更简单的方法,但关键是你要创建一个正确类型的数组。
答案 1 :(得分:1)
以下是'正确'的方法。通过反射处理数组有点难看:
// assume that property is an array of some enum
var enumType = property.PropertyType.GetElementType();
var values = value.Split(',');
var enumArray = Array.CreateInstance(enumType, values.Length);
for (int i = 0; i < enumArray.Length; ++i)
enumArray.SetValue(Enum.Parse(enumType, values[i]), i);
property.SetValue(x, enumArray);
重点是您需要使用正确的元素类型创建数组。如果您只使用ToArray
,那么最多只会得到int[]
,最差的是object[]
。
你可以实际将int[]
数组设置为枚举数组属性(只要枚举有int
作为其基础类型)。这只是对您的第一个示例的轻微更改,您不需要提供第三个参数:
property.SetValue(x, value.Split(',').Select(i => int.Parse(i)).ToArray());
但是,设置为此属性的数组将具有“错误”类型。我不确定这是否会导致任何问题,但如果您正在进行大量依赖于运行时类型的反射,则可能会遇到一些问题。 (如果要解析命名的枚举值,这也不起作用。)
答案 2 :(得分:0)
使用通用方法执行此操作的另一种方法:
public class Class2
{
public enum TestEnum
{
One = 1,
Two = 2,
Three = 3
}
public TestEnum[] TestValues { get; set; }
public static T[] ConvertToEnum<T>(IEnumerable<int> values)
{
return values
.Select(v => (T)Enum.ToObject(typeof(T), v))
.ToArray();
}
public void Test()
{
var property = this.GetType().GetProperty("TestValues");
var value = "1,2,3";
var convert = this.GetType()
.GetMethod("ConvertToEnum")
.MakeGenericMethod(property.PropertyType.GetElementType());
var intValues = value.Split(',').Select(v => int.Parse(v));
var result = convert.Invoke(null, new[] { intValues });
property.SetValue(this, result, null);
}
}
重点是使数组创建更具可读性。额外奖励:ConvertToEnum<T>
方法可以在其他地方重复使用。