inheritance类的输出无效
我有2节课
[DataContract, KnownType(typeof(B))] public class A { [DataMember] public string prop1 { get; set; } [DataMember] public string prop2 { get; set; } [DataMember] public string prop3 { get; set; } } [DataContract] public class B : A { [DataMember] public string prop4 { get; set; } }
以及以下方法:
List BList = new List(); BList = new List() { new B() { prop1 = "1", prop2 = "2", prop3 = "3", prop4 = "4" } }; List AList = BList.Cast().ToList(); DataContractSerializer ser = new DataContractSerializer(typeof(List)); FileStream fs = new FileStream(@"C:\temp\AResult.xml", FileMode.Create); using (fs) { ser.WriteObject(fs, AList); }
将其写入输出的XML文件:
1 2 3 4
怎么可能发生, prop4
在结果范围内,我怎么能避免这种情况? prop4
不是正在序列化的List
一部分。
这是因为您在AList中存储指向B对象实例的指针。 当你执行“new B(){prop1 =”1“,prop2 =”2“,prop3 =”3“,prop4 =”4“}”你创建了一个B对象实例。 当序列化程序反映存储在AList中的对象时,它会找到一个实际的B对象实例,因为你没有更改B对象实例,只能将它存储在AList中。 编译器允许你这样做,因为inheritance链允许它,但B对象实例没有改变,那么它是一个B对象实例,无论你存储它的地方。
而不是做:
List AList = BList.Cast().ToList();
做:
List AList = BList.Select(b => new A() { prop1 = b.prop1, prop2 = b.prop2, prop3 = b.prop3 }) .ToList();
这将为BList中的每个B实例创建一个新的A实例
DataContractResolver允许您自定义DataContract的解析方式。 在这种情况下,您只需要将子类型解析为基本类型。
以下代码来自此博客文章。
public class DeserializeAsBaseResolver : DataContractResolver { public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) { return knownTypeResolver.TryResolveType(type, declaredType, null, out typeName, out typeNamespace); } public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) { return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ?? declaredType; } }
根据框架,将上面的类传递给datacontract序列化程序,它应该为您提供所需的结果。
DataContractSerializer ser = new DataContractSerializer(typeof(List));), null, Int32.MaxValue, false, false, null, new DeserializeAsBaseResolver ());
在C#中向下转换的一种简单方法是序列化子进程,然后将其反序列化为父进程。
List BList = new List(); BList = new List() { new B() { prop1 = "1", prop2 = "2", prop3 = "3", prop4 = "4" } }; var serializedChildList = JsonConvert.SerializeObject(BList); List AList = JsonConvert.DeserializeObject
样本输出:
1 2 3
如果您还没有像其中一条评论中提到的那样自己完成,那么这里有一些我编写的代码。 我暂时没有使用AutoMapper
,所以我不记得并找出如何映射List
类型。 无论如何,这里是小提琴:
var list = new List { new B { prop1 = "1", prop2 = "2", prop3 = "3", prop4 = "4" } }; Mapper.Initialize(i => i.CreateMap()); using (var stream = new FileStream(@"output.xml", FileMode.Create)) { var serializer = new DataContractSerializer(typeof(List)); serializer.WriteObject(stream, list.Select(i => Mapper.Map(i)).ToList()); }