我正在尝试通过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。
答案 0 :(得分:9)
最好的办法是停止使用NameValueCollection
和ArrayList
等弱类型。请改用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();