0

リフレクションを使用して、一部の OpenXML タイプ (Justification など) のプロパティを設定しようとしています。すべての可能性を列挙して値を割り当てるのは簡単です。

// attr is an XmlAttribute, so .Name and .Value are Strings
if (attr.Name == "Val")
{
    if (element is Justification)
    {
        ((Justification)element).Val = (JustificationValues)Enum.Parse(typeof(JustificationValues), attr.Value);
            return;
    }
    else
    {
        // test for dozens of other types, such as TabStop
    }
}

リフレクションを介してこれを行うのが難しい理由は次のとおりです。1) Val プロパティの型は EnumValue<T> であるため、Enum.Parse の最初の引数として渡す型を抽出する方法がわかりません。2) 実際の列挙型から EnumValue<> 型への暗黙の変換がありますが、これをリフレクションで呼び出す方法がわかりません。

コードを次のようにしたいと思います。

PropertyInfo pInfo = element.GetType().GetProperty(attr.Name);
Object value = ConvertToPropType(pInfo.PropertyType, attr.Value); /* this 
    would return an instance of EnumValue<JustificationValues> in this case */
pInfo.SetValue(element, value, null);

ConvertToPropType を実装するにはどうすればよいですか? または、より良い解決策はありますか?

ありがとう

編集:Earwickerの提案を使用して解決策を見つけましたが、列挙型の型名はノードの型名から派生できるという便利な事実に依存しています(「Justification」->「JustificationValues」)。ただし、一般的なケースでこれを解決する方法にはまだ興味があります。

Edit2: GetGenericArguments は、残りの道を私にもたらしました。ありがとう。

4

3 に答える 3

4

属性値が単なる文字列である場合、文字列が特定の列挙型の値を識別することを理解する何らかの方法がすでにあると思います。あなたの例ではハードコードされているので、それがあなたが望むものなのか、それとも変更したいのかわかりません。

それが列挙型であり、どの列挙型であるかを知っていると仮定するとenum、スニペットのように、正しい型のボックス化された値を含むオブジェクトを取得する方法は既にわかっています。

EnumValue<T>を受け取るコンストラクターがあると仮定すると、 T.

Type genericType = typeof(EnumValue<>);
Type concreteType = genericType.MakeGenericType(typeof(JustificationValues));

concreteTypeはタイプEnumValue<JustificationValues>です。

JustificationValuesそこから、できればパラメーターを受け取るコンストラクターを取得できますInvoke

アップデート

ああ、私はあなたが今何をしているのか分かります。XML 属性名を使用して C# プロパティを選択します。EnumValue<T>そのプロパティが typeであるかどうかを検出し、それが何であるかを調べることができる必要がありますT

PropertyInfo p = // ... get property info

Type t = p.GetType();

if (t.IsGenericType && 
    t.GetGenericTypeDefinition == typeof(EnumValue<>))
{
    Type e = t.GetGenericArguments()[0]; // get first (and only) type arg

    // e is the enum type...

試してみてください。

于 2009-07-20T17:58:25.123 に答える
1

.Net 4.0 では、レイト バインドの暗黙的または明示的な変換を行うためのサポートが追加されています。これは、オープン ソース フレームワークImpromptuInterfaceでInvokeConvertと呼ばれる静的メソッドで簡略化されています。あなたの理想的な例では、次のように機能します。

PropertyInfo pInfo = element.GetType().GetProperty(attr.Name);
Object value = Impromptu.InvokeConvert(attr.Value, pInfo.PropertyType); 
pInfo.SetValue(element, value, null);
于 2011-04-18T15:40:53.607 に答える
1

これは基本的なタイプでのみ機能する可能性がありますが、私がやっていることには十分でした

PropertyInfo pInfo = element.GetType().GetProperty(attr.Name);
Object value = System.Convert.ChangeType(attr.Value, pInfo.PropertyType);
pInfo.SetValue(element, value, null);
于 2011-05-17T05:25:46.587 に答える