3

linqtoXmlは初めてです。与えられた再帰の深さの相関するサブツリールートを表す方法でXMLデータを保持する必要がある
パラメーターとして取得する再帰メソッドがあります。XElement root

void recursiveMethod(XElement root);
具体的には、次のXMLの例も参照してください。

<start>
      <Class>
           <Worker>
                <Name> Dan </Name>
                <Phone> 123 </Phone> 
                <Class>
                      <Address>
                           <Street> yellow brick road </Street>
                           <Zip Code> 123456 </Zip Code>
                      </Address>
                </Class>
            </Worker>
      </Class>
...
</start>    

ご想像のとおり、Nameは値型Addressですが、はクラス参照です。
Xml情報は、リフレクションを介して動的に追加する必要があります(トップダウンアプローチ)。

長い話を短くするために、私がクラスを調査している途中でWorkerクラスに到達Addressし、「ドリルダウン」したいと想像してください。したがって、現在のワーカークラスの子ノードの正しい参照を使用して再帰メソッドを呼び出します。新しいXElementルートなので、以下のAddressクラス1の再帰深度 での反射によって見つけたものを追加できます。

この参照はXElementタイプである必要があることに注意してください。

どうやってやるの?

編集:あなたがこれらすべてのことをするという別の考えを持っているが、それを使わないのであれば、私はパラメータXElementでそれを好むが、私も聞いてうれしいです。XElement

別の問題
すべてのフィールド(FieldInfo []の変数)を反復処理するような単純な方法で実装を開始しました。値型(IsValueType)に遭遇した場合は、次のようなことをしていました。

 root.Add(new XElement("Field",
                      new XElement("Type", ...),
                      new XElement("Variable Name", ...),
                      new XElement("Value", ...)));     

したがって、一般的な知識のために:
1.ノードの子孫への参照のみを取得する方法がありました。これにより、より低い再帰レベルで、上記のように別のroot.Add(...)を実行できるようになります。このルートは、前のルートの子への参照になりますか?(これは、Linq構文なしで操作全体を実行することを意味します)

2.プロパティを操作せずにリフレクションを介してプライベートフィールドの値を取得できましたが、問題がありますか?常にリフレクションのプロパティを介して値を取得する必要がありますか?

4

1 に答える 1

5

この拡張メソッドは、必要な形式でXElementを構築します。

public static class Extensions
{
    public static XElement ToXml<T>(this T obj)
    {
        Type type = typeof(T);

        return new XElement("Class",
                    new XElement(type.Name,
                        from pi in type.GetProperties()
                        where !pi.GetIndexParameters().Any()
                        let value = (dynamic)pi.GetValue(obj, null)
                        select pi.PropertyType.IsPrimitive || 
                               pi.PropertyType == typeof(string) ?
                                new XElement(pi.Name, value) : 
                                Extensions.ToXml(value)
                        )
                    );
    }
}

ここでは何が起きるのですか:

  • 渡されたオブジェクトのパブリックプロパティを取得します(BindingFlagsをフィルタープロパティに追加できます)。
  • 次に、プロパティにインデックスパラメータがあるかどうかを確認し、そのようなプロパティをスキップします。
  • 次に、プロパティ値をdynamicオブジェクトとして取得します。重要です。そうしないと、メソッドobjectの再帰呼び出し時のようにプロパティ値タイプが推測されます。ToXml<T>
  • プロパティタイプがプリミティブタイプ(int、byte、long、single、doubleなど)か文字列かを確認します
  • プリミティブ型の場合、プロパティ値を使用して要素を記述します。他のタイプ(複雑)の場合、XElementの構築を再帰的に開始します

使用法:

Worker worker = new Worker()
{
    Name = "Serge",
    Phone = "911",
    Address = new Address() { Street = "Elm street", ZipCode = 666 }
};

XElement xml = worker.ToXml();

結果:

<Class>
  <Worker>
    <Name>Serge</Name>
    <Phone>911</Phone>
    <Class>
      <Address>
        <Street>Elm street</Street>
        <ZipCode>666</ZipCode>
      </Address>
    </Class>
  </Worker>
</Class>

ただし 、2つのオブジェクトが相互に参照する状況には注意する必要があります(この場合、無限再帰が発生します)

この場合、辞書やハッシュセットなどを使用して、xmlにすでに存在するすべてのオブジェクトを格納できます。

Type type = obj.GetType();
if (set.Contains(obj))
    return new XElement("Class", new XAttribute("name", type.Name));
set.Add(obj);
return new XElement("Class", ...);
于 2012-12-15T16:33:08.573 に答える