3

我有一个读取一些 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 返回一个 object[] 并再次引发解析错误。

我想写这个好像枚举类型是未知的。

有任何想法吗?

4

3 回答 3

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)

可能有更简单的方法,但关键是您创建了一个正确类型的数组。

于 2012-09-07T12:00:31.530 回答
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());

但是,设置为此属性的数组将具有“错误”类型。我不确定这是否真的会导致任何问题,但如果您进行大量依赖运行时类型的反射,您可能会遇到一些问题。(如果您想解析命名的枚举值,这也不起作用。)

于 2012-09-07T12:01:44.607 回答
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>方法可以在其他地方重复使用。

于 2012-09-07T12:09:21.390 回答