Frage

Dies ist eine sehr komplizierte Frage, wie Daten über einen Web-Service-Aufruf serialisiert werden, wenn die Daten nicht-stark typisiert. Ich werde versuchen, es zu legen, wie es am besten möglich.

Probenlagerung Objekt:

[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; }
}

Beispiel zu verwenden:

[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;
    }

Rückgabewert von Web Service:

<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>

Was ich will:

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

Der Grund & Other Stuff:

Erstens, ich bin für die Länge der Post leid, aber ich wollte auch reproduzierbar Code geben.

Ich will es in diesem Format, weil ich den Web-Service von PHP bin raubend. Ich möchte einfach gehen:

// Das ist imporant

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

Wenn es in dem anderen Format ist, dann gäbe es keine Möglichkeit für mich, das zu erreichen, die alle auf.

: in C # Außerdem, wenn ich den Dienst am raubend, würde ich die folgenden auch gerne in der Lage sein zu tun

// Das ist imporant

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

Leider bin ich nicht sicher, wie dies zu erreichen. Ich konnte es auf diese Weise erhalten, indem Sie eine benutzerdefinierte Wörterbuch erstellen, die IXmlSerializer implementiert (siehe Stackoverflow: IXmlSerializer Dictionary ), aber es blies das WSDL-Schema aus dem Wasser. Es ist auch viel zu kompliziert, und produzierte schreckliche Ergebnisse in meiner WinFormsTester Anwendung!

Gibt es eine Möglichkeit, dies zu erreichen? Welche Art von Objekten muss ich schaffen? Gibt es eine Möglichkeit, dies / außer, indem sie eine stark typisierte Sammlung zu tun /? Natürlich, wenn ich es stark wie folgt eingegeben:

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

Dann wäre es perfekt funktionieren, würde ich keine WSDL Probleme hat, würde ich in der Lage sein, um es leicht von PHP zugreifen, und C # (.OtherInfo.Hobbies).

Allerdings würde ich völlig den Punkt der NVP des verlieren, dass ich hätte im Voraus wissen, was die Liste ist, und es wäre unveränderlich .. sagen wir, aus einer Datenbank.

Danke an alle !! Ich hoffe, dass wir in der Lage sind, mit irgendeiner Art von Lösung für dieses Problem zu entwickeln. Hier sind die Anforderungen wieder:

  1. WSDL-Schema sollte nicht brechen
  2. Name-Wert-Paare (NVP ist) sollte in Attribut-Format serialisiert werden
  3. Sollte einfach namentlich NVP ist in PHP für den Zugriff auf [ "Hobbys"]
  4. Sollte für den Zugriff in C # leicht sein (und es ist Proxy-Generator kompatibel sein)
  5. Seien Sie leicht serializable
  6. erfordern mich nicht zu stark die Daten eingeben

Nun, ich bin / komplett / offen für alles auf eine bessere / andere Art und Weise, dies zu tun. Ich Speicherung einige relativ „statische“ Informationen (wie Name), und eine Reihe von Stücken von Daten. Wenn es eine bessere Art und Weise ist, würde ich gerne hören.

War es hilfreich?

Lösung

Das ist wie dynamische Eigenschaften für ein Objekt. C # ist nicht ganz dynamische Sprache im Gegensatz zu JavaScript oder vielleicht PHP die Objekteigenschaften on the fly analysieren kann. Die folgenden beiden Methoden sind das, was ich mir vorstellen kann. Der zweite könnte in Ihren Anforderungen entsprechen.

Die KISS Way

Keep It Simple Stupid Art und Weise

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

Sie können Name-Wert-Paare haben, die durch getrennt ist ‚|‘

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

serialisierten Formen

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

Die Dynamic Way in C #

Machen Sie den Namen Wertepaar Teil ein XML-Element werden, so dass Sie es dynamisch aufbauen können.

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

Sie können ganz einfach aufbauen Otherinfo Objekt als Element centric z.B.

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

Die serialisierte Form wird

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

oder bauen sie als Attribut centric

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>

Für jede dynamische Sprache, kann es direkt auf die Eigenschaften zugreifen. Im übrigen können sie den Wert zugreifen, indem Sie die XML lesen. Lesen von XML unterstützt wird auch von den meisten Rahmen.

Andere Tipps

Das ist, was ich angesiedelt auf.

Klassenstruktur:

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; }
}

Verbrauch:

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

Ausgabe:

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

Ich möchte allen für ihre Unterstützung danken, ich schätze die Hilfe und Ideen.

Als völlig andere Perspektive auf das, warum es nicht denkt ganz anders zu tun. Haben ein Web-Service-Methode, um die serialisierten Speicherobjekt zurückzukehren, abzüglich der OtherInfo und eine andere Methode, um die Liste von Eigenschaften (Schlüssel) für OtherInfo zurückzukehren, und eine dritte, die Liste der Werte für eine Taste, um zurückzukehren. Zugegeben, es wird mehr Umläufe an den Web-Service in Anspruch nehmen, wenn Sie alle Daten wollen, aber die Lösung wird viel einfacher und flexibler sein.

[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];
}

Haben Sie einen Blick in das Attribut System.Xml.Serialization.XmlSerializerAssemblyAttribute. Auf diese Weise können Sie eine benutzerdefinierte Klasse-Ebene Serializer angeben. Sie werden in der Lage sein, ausspucken, was XML Sie mögen.

Eine schnelle Möglichkeit, diese zu beschleunigen auf aufstehen ist sgen.exe zu verwenden, um einen zu generieren und einen Blick auf sich mit Reflektor hat.

-Oisin

Ich bin nicht sicher, das Ihr Problem lösen würde (es ist in C # würde, aber vielleicht nicht in PHP), sondern versucht, Dictionary<string,List<string>> OtherInfo anstelle von List<NameValuePairs>. Dann würden „Hobby“ und „Websites“ Ihre Schlüssel und die Werte würden die Liste der Hobbys oder Web-Sites sein. Ich bin nicht sicher, wie es wäre serialisiert, though.

würden Sie in der Lage sein, die Listen von Hobbys wie zu verweisen:

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

[EDIT] Siehe hier für eine allgemeine XML-serialisierbar Wörterbuch. Diese abgeleitete Klasse ist, die Sie benötigen würde, anstatt allgemeine Wörterbuch zu verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top