7

これは、データが強く入力されていない場合に、Webサービス呼び出しを介してデータをシリアル化する方法に関する非常に複雑な質問です。可能な限りレイアウトするようにします。

サンプルストレージオブジェクト:

[Serializable]
public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  public List<NameValuePairs> OtherInfo { get; set; }  
}
[Serializable]   
public class NameValuePairs {
  public string Name { get; set; }
  public string Value { get; set; }
}

使用例:

[WebMethod]
    public List<StorageObject> GetStorageObjects() {
      List<StorageObject> o = new List<StorageObject>() {
        new StorageObject() { 
          Name = "Matthew",
          Birthday = "Jan 1st, 2008", 
          OtherInfo = new List<NameValuePairs>() {
            new NameValuePairs() { Name = "Hobbies", Value = "Programming" },
            new NameValuePairs() { Name = "Website", Value = "Stackoverflow.com" }
          }
        },
        new StorageObject() { 
          Name = "Joe",
          Birthday = "Jan 10th, 2008",
          OtherInfo = new List<NameValuePairs>() { 
            new NameValuePairs() { Name = "Hobbies", Value = "Programming" },
            new NameValuePairs() { Name = "Website", Value = "Stackoverflow.com" }
          }
        }
      };

      return o;
    }

Webサービスからの戻り値:

<StorageObject>
    <Name>Matthew</Name>
    <Birthday>Jan 1st, 2008</Birthday>
    <OtherInfo>
        <NameValuePairs>
            <Name>Hobbies</Name>
            <Value>Programming</Value>
        </NameValuePairs>
        <NameValuePairs>
            <Name>Website</Name>
            <Value>Stackoverflow.com</Value>
        </NameValuePairs>
    </OtherInfo>
</StorageObject>

私が欲しいもの:

<OtherInfo>
    <Hobbies>Programming</Hobbies>
    <Website>Stackoverflow.com</Website>
</OtherInfo>

理由とその他のもの:

まず、投稿の長さについては申し訳ありませんが、再現可能なコードも提供したいと思いました。

PHPからWebサービスを利用しているので、この形式で使用したいと思います。簡単に行きたい:

//これは重要です

In PHP => "$Result["StorageObject"]["OtherInfo"]["Hobbies"]".  

それが他の形式である場合、それを達成する方法はまったくありません。さらに、C#でサービスを利用している場合は、次のこともできるようにしたいと思います。

//これは重要です

In C# => var m = ServiceResult[0].OtherInfo["Hobbies"];

残念ながら、これを実現する方法がわかりません。IXmlSerializerを実装したカスタムディクショナリを構築することで( StackOverflow:IXmlSerializerディクショナリを参照)、この方法で取得できましたが、WSDLスキーマが水から吹き飛ばされました。また、非常に複雑で、WinFormsTesterアプリケーションでひどい結果をもたらしました。

これを達成する方法はありますか?どのタイプのオブジェクトを作成する必要がありますか?/強く型付けされたコレクションを作成する以外に/これを行う方法はありますか?明らかに、私がそれをこのように強くタイプした場合:

public class OtherInfo {
  public string Hobbies { get; set; }
  public string FavoriteWebsite { get; set; }
}

そうすれば、完全に機能し、WSDLの問題は発生せず、PHPおよびC#(.OtherInfo.Hobbies)から簡単にアクセスできるようになります。

ただし、リストが何であるかを事前に知る必要があり、データベースから変更できないという点で、NVPのポイントを完全に失うことになります。

みんな、ありがとう!!これに対する何らかの解決策を考え出すことができるといいのですが。再度要件は次のとおりです。

  1. WSDLスキーマは壊れてはいけません
  2. 名前と値のペア(NVP)は、属性形式にシリアル化する必要があります
  3. PHPのNVPに名前で簡単にアクセスできる必要があります["趣味"]
  4. C#で簡単にアクセスできる(そしてプロキシジェネレーターと互換性がある)必要があります
  5. 簡単にシリアル化可能
  6. データを強く入力する必要はありません

今、私はこれを行うためのより良い/異なる方法について/完全に/入力することを開いています。比較的「静的な」情報(Nameなど)と大量のデータを保存しています。もっと良い方法があれば、聞いてみたいです。

4

5 に答える 5

5

これは、オブジェクトの動的プロパティのようなものです。C#は、JavaScriptとは異なり、完全に動的な言語ではありません。あるいは、PHPがオブジェクトのプロパティをその場で解析できる場合もあります。次の2つの方法が私が考えることができるものです。2つ目は、要件に適合する場合があります。

KISSウェイ

シンプルに保つ愚かな方法

public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  public List<string> OtherInfo { get; set; }  
}

'|'で区切られた名前と値のペアを持つことができます

OtherInfo = {"Hobbies|Programming", "Website|Stackoverflow.com"}

シリアル化されたフォーム

<StorageObject>
    <Name>Matthew</Name>
    <Birthday>Jan 1st, 2008</Birthday>
    <OtherInfo>
        <string>Hobbies|Programming</string>
        <string>Website|Stackoverflow.com</string>
    </OtherInfo>
</StorageObject>

C#の動的な方法

名前と値のペアの部分をXML要素にして、動的に作成できるようにします。

public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  public XElement OtherInfo { get; set; } // XmlElement for dot net 2
}

OtherInfoオブジェクトを要素中心として簡単に構築できます。

XElement OtherInfo = new XElement("OtherInfo");
OtherInfo.Add( ..Hobbies xelement & text value..);
OtherInfo.Add( ..WebSite xelement & text value..);

シリアル化されたフォームは

<OtherInfo>
    <Hobbies>Programming</Hobbies>
    <Website>Stackoverflow.com</Website>
</OtherInfo>

または属性中心として構築します

XElement OtherInfo = new XElement("OtherInfo");
OtherInfo.Add( ..nvp xattribute Hobbies & value..);
OtherInfo.Add( ..nvp xattribute WebSite & value..);

<OtherInfo>
    <nvp n="Hobbies" v="Programming" />
    <nvp n="Website" v="Stackoverflow.com" />
</OtherInfo>

動的言語の場合、プロパティに直接アクセスできます。残りの部分については、XMLを読み取ることで値にアクセスできます。XMLの読み取りは、ほとんどのフレームワークで十分にサポートされています。

于 2008-11-01T02:17:33.987 に答える
4

これが私が決めたものです。

クラス構造:

public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  [XmlAnyElement("Info")]  // this prevents double-nodes in the XML
  public XElement OtherInfo { get; set; }
}

使用法:

StorageObject o = new StorageObject();
o.OtherInfo.Add(new XElement("Hobbies","Programming");
o.OtherInfo.Add(new XElement("Website","Stackoverflow.com");

出力:

<Info>
  <Hobbies>Programming</Hobbies>
  <Website>Stackoverflow.com</Website>
</Info>

皆様のご支援に感謝申し上げます。ご協力とアイデアに心より感謝申し上げます。

于 2008-11-01T03:16:47.847 に答える
1

これに対するまったく異なる見方として、まったく異なる方法でそれを行うことを考えてみませんか。シリアル化されたストレージオブジェクトを返す1つのWebサービスメソッドと、OtherInfoのプロパティ(キー)のリストを返す別のメソッドOtherInfo、および任意のキーの値のリストを返す3番目のメソッドを用意します。確かに、すべてのデータが必要な場合は、Webサービスへのラウンドトリップが長くなりますが、ソリューションははるかに単純で柔軟性があります。

[Serializable]
public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }

  [Nonserializable]
  public Dictionary<string,List<string>> OtherInfo { get; set; }  
}

[WebMethod]
public List<StorageObject> GetStorageObjects() {
    // returns list of storage objects from persistent storage or cache
}

[WebMethod]
public List<string> GetStorageObjectAttributes( string name )
{
    // find storage object, sObj
    return sObj.Keys.ToList();
}

[WebMethod]
public List<string> GetStorageObjectAtributeValues( sting name, string attribute )
{
    // find storage object, sObj
    return sObj[attribute];
}
于 2008-11-01T03:04:13.800 に答える
0

System.Xml.Serialization.XmlSerializerAssemblyAttribute属性を調べてください。これにより、カスタムのクラスレベルのシリアライザーを指定できます。好きなXMLを吐き出すことができます。

これらを理解するための簡単な方法は、sgen.exeを使用して生成し、Reflectorで確認することです。

-オシーン

于 2008-11-01T02:07:00.657 に答える
-1

これで問題が解決するかどうかはわかりませんが(C#では解決しますが、PHPでは解決しない可能性があります)、Dictionary<string,List<string>> OtherInfoの代わりにを使用してみてくださいList<NameValuePairs>。次に、「趣味」と「Webサイト」がキーになり、値は趣味またはWebサイトのリストになります。ただし、どのようにシリアル化されるかはわかりません。

趣味のリストは次のように参照できます。

List<string> hobbies = storageObject.OtherInfo["Hobbies"];

[編集]一般的なXMLシリアル化可能辞書については、こちらを参照してください。この派生クラスは、ジェネリックDictionaryの代わりに使用する必要があるクラスです。

于 2008-11-01T02:03:55.637 に答える