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 []であり、これは解析エラーをスローします。2番目の場合も同様ですが、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[]

実際には、配列をenum配列プロパティに設定できますint[](enumがその基になる型と同じである限りint)。これは最初の例のほんのわずかな変更であり、3番目の引数を指定する必要はありません。

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 に答える