使用NameValueCollection的WCF序列化问题

时间:2009-06-02 11:57:12

标签: c# wcf serialization

我正在尝试通过WCF序列化NameValueCollection。我不断收到异常,告诉我一个接一个地添加一个类型。添加它们之后,我终于得到了

  

类型'System.Object []'无法添加到已知类型列表中,因为已存在具有相同数据协定名称“http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfanyType”的其他类型“System.Collections.ArrayList”。

合同现在看起来像这样:

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

我真的不知道如何能够序列化我的NameValueColletion。

另一个奇怪的事情是编译器警告不推荐使用CaseInsensitiveHashCodeProvider。

4 个答案:

答案 0 :(得分:9)

最好的办法是停止使用NameValueCollectionArrayList等弱类型。请改用Dictionary<string,string>List<T>

答案 1 :(得分:4)

NameValueCollection似乎并不完全是针对此用例设计的。 a series上有of blog posts this blog处理此问题并提供a possible solution(以及使用IDictionary ) 。我没有测试过它。

答案 2 :(得分:3)

另一种方法可能是使用包装类来使NameValueCollection适应WCF序列化。这是一个简单的示例,它将每个名称 - 值对序列化为单个逗号分隔的字符串。然后它在反序列化时将该值读回NameValueCollection

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

这将允许您在[DataMember]上使用该类型作为标准DataContract属性,并且您还将使用标准WCF序列化技术。

答案 3 :(得分:1)

NameValueCollection不直接实现ICollection接口。相反,NameValueCollection扩展了NameObjectCollectionBase。这实现了ICollection接口,并且NameValueCollection类中未实现重载的Add(system.string)方法。当您使用XMLSerializer时,XmlSerializer会尝试将NameValueCollection序列化或反序列化为通用ICollection。因此,它查找默认的Add(System.String)。如果没有Add(system.String)方法,则抛出异常。

使用SoapFormatter类进行序列化,而不是使用XML序列化。要使用SoapFormatter类,必须添加对System.Runtime.Serialization.Formatters.Soap.dll的引用。

// 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();