2

テンプレート (デフォルト値) と指定されたフィールドを含む非標準の XML があります。例として、いつでも歓迎します:

<MyClass>
   <ArrayOfSubClass>
      <SubClass>
         <Par1>1</Par1>
         <Par2>2</Par2>
         <Par3>3</Par3>
         <ArrayOfSpecific>
            <Specific>
               <Par1>11</Par1>
            </Specific>
         </ArrayOfSpecific>
      </SubClass>
   </ArrayOfSubClass>
</MyClass>

MyClassこのクラスをオブジェクトにデシリアライズしたい。ご覧のとおり、MyClassSubClass3 つのパラメーターとクラスのコレクションを持つクラスのコレクションですSpecific。クラスSubClassSpecificは、同じマザー クラスから派生します。

ISpecific フィールドが指定されていない場合、デフォルト値 (つまり、 で見つかった値) を見つけたいと思いますSubClass。私がこれまでに行ったことは、クラスSpecificのプロパティにプロパティ タイプのデフォルト値があるかどうかをリフレクションによってチェックし、そうである場合はそれをのプロパティに置き換えるメソッドを実装するSubClassことです。非常にうまく機能しますが、すべてのケースをカバーしているわけではありません。たとえば、 に double プロパティの値があるとPar1します。問題は、それが double 型のデフォルト値であるため、私の方法では、.SubClassPar1 = 1.23400SubClass

最初にオブジェクトをデシリアライズしてから、同じプロパティの値を持つMyClassクラスのすべてのプロパティを に配置し、この既存のオブジェクトにデシリアライズして、XML ファイルで指定されたプロパティのみを変更するのが最善でした。SpecificSubClass

非常にトリッキーなので、私の質問が理解しにくいと想像できます...

[編集:] わかりやすくするために、デシリアライズした結果を次に示します。

<MyClass>
   <ArrayOfSubClass>
      <SubClass>
         <Par1>1</Par1>
         <Par2>2</Par2>
         <Par3>3</Par3>
         <ArrayOfSpecific>
            <Specific>
               <Par1>11</Par1>
               <Par2>2</Par2>
               <Par3>3</Par3>
            </Specific>
         </ArrayOfSpecific>
      </SubClass>
   </ArrayOfSubClass>
</MyClass>

Specificのプロパティにデフォルト値がある場合は、逆シリアル化後にリフレクションによって行われ、クラスの値を取得しますSubClass。トリッキーなケースは次のとおりです

<MyClass>
   <ArrayOfSubClass>
      <SubClass>
         <Par1>1</Par1>
         <Par2>2</Par2>
         <Par3>3</Par3>
         <ArrayOfSpecific>
            <Specific>
               <Par1>0</Par1> <----- 0 is the default value of a double
            </Specific>
         </ArrayOfSpecific>
      </SubClass>
   </ArrayOfSubClass>
</MyClass>

現在、結果は

<MyClass>
   <ArrayOfSubClass>
      <SubClass>
         <Par1>1</Par1>
         <Par2>2</Par2>
         <Par3>3</Par3>
         <ArrayOfSpecific>
            <Specific>
               <Par1>1</Par1>   <---- as 0 is the default value of a double, this property is set to the value of the SubClass
               <Par2>2</Par2>
               <Par3>3</Par3>
            </Specific>
         </ArrayOfSpecific>
      </SubClass>
   </ArrayOfSubClass>
</MyClass>

でも私はしたい

<MyClass>
   <ArrayOfSubClass>
      <SubClass>
         <Par1>1</Par1>
         <Par2>2</Par2>
         <Par3>3</Par3>
         <ArrayOfSpecific>
            <Specific>
               <Par1>0</Par1>
               <Par2>2</Par2>
               <Par3>3</Par3>
            </Specific>
         </ArrayOfSpecific>
      </SubClass>
   </ArrayOfSubClass>
</MyClass>
4

2 に答える 2

0

これは、有益なシリアル化のための CodeProject リンクのコレクションです。

私はあなたの質問を理解しているかどうか確信が持てませんが、クラスをシリアライズ可能にして、MyClass の例で適切な値のシリアライゼーションをコーディングしていただけないでしょうか?

于 2013-01-10T19:55:43.397 に答える
0

わかりました、私の問題を解決する回避策を見つけました。私はこれを 2 つの (実際には 3 つの) ステップで行います。まず、XML をクラスに逆シリアル化します。次に、クラスのすべてのプロパティを、リフレクションでSpecific見つけた既定値に設定します。1 つのフィールド (クラスの If) が必要です。そして 3 番目に、XML を. そこで、namedを調べ、クラスのすべてのプロパティについて、同じ名前の列があるかどうかを調べ、セルに値が含まれている場合はそれをクラスに入れます。SubClassSpecificDataSetDataTableSpecific

ふふっふっ!!!! 本当に美しさではありませんが、機能します。

     DataSet xmlDS = new DataSet();
     xmlDS.ReadXml(filename);
     GetSpecifiedValuesInDataSet(xmlDS);

     DataTable table = xmlDS.Tables["Specific"];

     foreach(ArrayOfSubClass array in this.Items)
     {
        foreach(SubClass sub in array)
        {
           foreach(Specific specific in sub)
           {
              Type specificType = specific.GetType();

              DataRow modelRow = null;
              foreach(DataRow row in table.Rows)
              {
                 if(row["Par1"].ToString().Equals(specific.Par1.ToString()))
                 {
                    modelRow = row;
                    break;
                 }
              }

              if(modelRow != null)
              {
                 foreach(PropertyInfo propSpecific in specificType.GetProperties())
                 {
                    string propertyName = propSpecific .Name;
                    foreach(DataColumn col in table.Columns)
                    {
                       if(col.ColumnName.Equals(propertyName))
                       {
                          if(!string.IsNullOrEmpty(modelRow[propertyName].ToString()))
                          {
                             object value = Convert.ChangeType(modelRow[propertyName], propSpecific.PropertyType);
                             propSpecific.SetValue(modelProd, value, null);
                          }
                       }
                    }
                 }
              }
           }
        }
     }

そして出来上がり

于 2013-01-10T22:13:35.707 に答える