我有一个应用程序,我需要将数据协定序列化程序用于不同但类似的类型:
根据Scrobi的要求,这是一个完整的模型示例:
[DataContract]
public class Model
{
public Model()
{
List = new List<int>(new[] {1, 2, 3});
Collection = new Collection<int>(new[] {4, 5, 6});
Array = new[] {7, 8, 9};
}
[DataMember]
public object List { get; set; }
[DataMember]
public object Collection { get; set; }
[DataMember]
public object Array { get; set; }
public string SerializeMe()
{
var serializer = new DataContractSerializer(typeof(Model), GetKnownTypes());
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, this); // exception
return Encoding.UTF8.GetString(stream.GetBuffer());
}
}
public static Type[] GetKnownTypes()
{
return new[]
{
typeof(List<int>),
typeof(Collection<int>), // error
typeof(int[]) // error
};
}
}
问题是:我无法同时添加通用List,Collection和数组,因为它们都使用相同的数据协定。
当我只使用其中一种集合类型时,我无法序列化其他集合类型,因为它们是未知的(数据合同存在,但对于另一种类型)。是的,这些字段必须是对象才能使其适用于我的情况(在实际应用程序中,我无法向它们添加属性)。
在我编写的应用程序中使用其中一种类型是非常不切实际的,因为它是一种开发环境,开发人员可以自由选择类型。
是否有针对此数据合同序列化程序限制的解决方法?
谢谢,
答案 0 :(得分:1)
我有部分答案,但出于某种原因,在测试时Collection<int>
在反序列化时会抛出错误。也许您可以使用它来找到完整的解决方案。
我创建了DataContractResolver
,允许您覆盖xsi:type
有一些文档here
public class MyResolver : DataContractResolver
{
public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
{
string name = string.Empty;
bool isFound = false;
if (type.Name == "Int32[]")
{
name = "IntArray";
isFound = true;
}
if (type.Name.Contains("List") && type.FullName.Contains("Int")) //find List<int>
{
name = "IntList";
isFound = true;
}
if (type.Name.Contains("Collection") && type.FullName.Contains("Int")) //find Collection<int>
{
name = "IntCollection";
isFound = true;
}
if (isFound)
{
XmlDictionary dictionary = new XmlDictionary();
typeName = dictionary.Add(name);
typeNamespace = dictionary.Add("http://tempuri.com");
return true;
}
return knownTypeResolver.TryResolveType(type, declaredType, knownTypeResolver, out typeName, out typeNamespace);
}
public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
{
if (typeName == "IntArray" )
{
return typeof(int[]);
}
if (typeName == "IntList")
{
return typeof(List<int>);
}
if (typeName == "IntCollection")
{
return typeof(Collection<int>);
}
return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null);
}
}
然后,您不需要GetKnownTypes()
并创建DataContractSerializer
,如下所示:
var serializer = new DataContractSerializer(typeof(Model),null, int.MaxValue, false, false,null, new MyResolver());
希望这有点帮助。