2009-06-02 13 views
5

Ich versuche, eine NameValueCollection über WCF zu serialisieren. Ich bekomme immer wieder Ausnahmen, die mir einen Typ nach dem anderen hinzufügen. Nach der Zugabe von ihnen, ich schließlichWCF-Serialisierungsproblem mit NameValueCollection

Typ ‚System.Object []‘ nicht zur Liste der bekannten Typen da eine andere Art ‚System.Collections.ArrayList‘ mit dem gleichen Datenvertragsnamen ‚http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfanyType‘ ist bereits hinzugefügt werden können Geschenk.

Der Vertrag sieht nun wie folgt aus:

[KnownType(typeof(NameValueCollection))] 
[KnownType(typeof(CaseInsensitiveHashCodeProvider))] 
[KnownType(typeof(CaseInsensitiveComparer))] 
[KnownType(typeof(string[]))] 
[KnownType(typeof(Object[]))] 
[KnownType(typeof(ArrayList))] 
[DataContract] 
public class MyClassDataBase 
{ 
    [DataMember] 
    public NameValueCollection DataCollection = new NameValueCollection(); 
} 

ich wirklich nicht wissen, was in der Lage sein zu tun, um meine NameValueColletion zu serialisiert.

Eine andere seltsame Sache ist, dass der Compiler warnt, dass der CaseInsensitiveHashCodeProvider veraltet ist.

Antwort

9

Die beste Idee wäre wie NameValueCollection und ArrayList mit schwachen Typen zu stoppen. Verwenden Sie stattdessen Dictionary<string,string> und List<T>.

+0

NameValueCollection ist schwach typisiert? – ironsam

+1

Ich habe den Begriff "schwacher Typ" verwendet, nicht "schwach typisiert". Damit meine ich, dass "NameValueCollection" in den Satz von Sammlertypen aufgenommen wird, der vor Generics eingeführt wurde. –

+0

Wenn ich Wörterbücher in WCF verwende, de-serialisieren sie nicht sehr gut. Oder etwas ist ausgeschaltet, wenn ich es deserialisiere. – micahhoover

4

Die NameValueCollection scheint nicht genau für diesen Anwendungsfall ausgelegt zu sein. Es gibt a seriesof blogposts auf this blog, die mit diesem Problem beschäftigt und präsentiert a possible solution (nämlich: eine IDictionary verwenden). Ich habe es aber nicht getestet.

1

NameValueCollection implementiert die ICollection-Schnittstelle nicht direkt. Stattdessen erweitert NameValueCollection NameObjectCollectionBase. Dies implementiert die ICollection-Schnittstelle und die überladene Add (system.string) -Methode ist nicht in der NameValueCollection-Klasse implementiert. Wenn Sie den XMLSerializer verwenden, versucht der XmlSerializer, die NameValueCollection als generische ICollection zu serialisieren oder zu deserialisieren. Daher sucht es nach dem Standard Add (System.String). Wenn die Methode Add (system.String) fehlt, wird die Ausnahme ausgelöst.

Verwenden Sie die SoapFormatter-Klasse für die Serialisierung, anstatt XML-Serialisierung zu verwenden. Um die SoapFormatter-Klasse zu verwenden, müssen Sie einen Verweis auf System.Runtime.Serialization.Formatters.Soap.dll hinzufügen.

// Serializing NameValueCollection object by using SoapFormatter 
SoapFormatter sf = new SoapFormatter(); 
Stream strm1 = File.Open(@"C:\datasoap.xml", FileMode.OpenOrCreate,FileAccess.ReadWrite); 
sf.Serialize(strm1,namValColl); 
strm1.Close(); 

// Deserializing the XML file into NameValueCollection object 
// by using SoapFormatter 
SoapFormatter sf1 = new SoapFormatter(); 
Stream strm2 = File.Open(@"C:\datasoap.xml", FileMode.Open,FileAccess.Read); 
NameValueCollection namValColl1 = (NameValueCollection)sf1.Deserialize(strm2); 
strm2.Close(); 
+0

Danke, ich löste das Problem, indem ich stattdessen das Dictionary benutzte, was in diesem Fall viel einfacher für mich war. – kaze

+0

ew, nein, benutze den SoapFormatter nicht. Interoperabilität wird brechen. – Cheeso

+1

@Kaze, dann ist die von Ihnen verwendete Lösung tatsächlich die, die Saunders vorgeschlagen hat. Obwohl Sie diese Antwort "akzeptiert" markiert haben, haben Sie tatsächlich eine andere Antwort verwendet. – Cheeso

3

Ein anderer Ansatz könnte darin bestehen, eine Wrapper-Klasse zu verwenden, um NameValueCollection an die WCF-Serialisierung anzupassen. Hier ist ein einfaches Beispiel, bei dem jedes Name-Wert-Paar als einzelne, durch Kommas getrennte Zeichenfolge serialisiert wird. Er liest dann den Wert wieder in den NameValueCollection auf Deserialisierung:

[CollectionDataContract] 
public class NameValueCollectionWrapper : IEnumerable 
{ 
    public NameValueCollectionWrapper() : this(new NameValueCollection()) { } 

    public NameValueCollectionWrapper(NameValueCollection nvc) 
    { 
     InnerCollection = nvc; 
    } 

    public NameValueCollection InnerCollection { get; private set; } 

    public void Add(object value) 
    { 
     var nvString = value as string; 
     if (nvString != null) 
     { 
      var nv = nvString.Split(','); 
      InnerCollection.Add(nv[0], nv[1]); 
     } 
    } 

    public IEnumerator GetEnumerator() 
    { 
     foreach (string key in InnerCollection) 
     { 
      yield return string.Format("{0},{1}", key, InnerCollection[key]); 
     } 
    } 
} 

Dies würde ermöglichen es Ihnen, den Typ als Standard [DataMember] Eigenschaft auf DataContract s zu verwenden, und Sie würden auch Standard WCF-Serialisierung Techniken verwenden.

Verwandte Themen