C# 防止属性序列化
这比SO上发布的其他类似问题中讨论的直截了当的场景要复杂一些 我有这样一个类的层次结构:C# 防止属性序列化,c#,vb.net,serialization,C#,Vb.net,Serialization,这比SO上发布的其他类似问题中讨论的直截了当的场景要复杂一些 我有这样一个类的层次结构: DrawingObject(abstract类,定义abstract属性Size和位置) 标签(继承绘图对象。提供了大小和位置的具体实现。这两个属性都应序列化) 行(在序列化/反序列化过程中应忽略继承的绘图对象大小和位置属性) 我正在使用DataContractSerializer序列化我的DrawingObjects,这会造成以下问题: 如果我没有用DataContract标记任何类,Ignor
(DrawingObject
类,定义abstract
属性abstract
和Size
)位置
(继承标签
。提供了绘图对象
和大小
的具体实现。这两个属性都应序列化)位置
(在序列化/反序列化过程中应忽略继承的行
绘图对象
和大小
属性)位置
DataContractSerializer
序列化我的DrawingObject
s,这会造成以下问题:
- 如果我没有用
标记任何类,DataContract
无效,IgnoreDataMember
/位置
属性将被序列化为大小
和标签
。我不想要的东西行
- 如果我在我的类上应用
,会生成一个运行时异常,告诉我DataContract
不能用DrawingObject
标记,因为它的基类DataContract
(是,MVVM灯)没有用observegeObject
属性标记DataContract
[DataContract]
和[DataMember]
属性将使DataContractSerializer
工作。如果省略这些属性,DataContractSerializer
将序列化该类的所有公共读/写属性(该类必须具有一个无公共参数的构造函数)。对于我的场景来说,这可能是一个好消息,但C#和VB.NET在这方面的表现似乎有点不同:
C#
以下代码正确序列化:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
namespace ConsoleApp1
{
public abstract class DrawingObject
{
public abstract string Location { get; set; }
public abstract string Size { get; set; }
}
public class Label : DrawingObject
{
public Label() { }
private string _Loc;
private string _Sz;
public override string Location { get { return _Loc; } set { _Loc = value; } }
public override string Size { get { return _Sz; } set { _Sz = value; } }
}
public class Line : DrawingObject
{
public Line() { }
public override string Location { get { return "Line Location"; } set { Console.WriteLine("Line.Location.set"); } }
public override string Size { get { return "Line Size"; } set { Console.WriteLine("Line.Size.set"); } }
}
class Program
{
static void Main(string[] args)
{
DrawingObject D1 = new Label() { Location="Label Loc", Size="Label Sz" } ;
DrawingObject D2 = new Line();
List<DrawingObject> DObjs = new List<DrawingObject>();
DObjs.Add(D1);
DObjs.Add(D2);
DataContractSerializer S = new DataContractSerializer(typeof(List<DrawingObject>), new[] { typeof(Line), typeof(Label) }, 0x7FFF, false, true, null);
var sb = new System.Text.StringBuilder();
using (var writer = new StringWriter(sb))
{
using (var xmlWriter = System.Xml.XmlWriter.Create(writer, new System.Xml.XmlWriterSettings() { Indent = true, OmitXmlDeclaration = false }))
S.WriteObject(xmlWriter, DObjs);
Console.WriteLine(sb.ToString());
Console.Read();
}
}
}
}
我试图使它们在语法上等价,但DataContractSerializer
的行为却不同
编辑2
我测试了@CodeCaster的建议,并将[IgnoreDataMember]
应用于行
对象的位置
属性。没有任何区别(位置
属性仍为行
序列化)。看起来,DataContractSerializer
在派生类中不尊重此属性。我还尝试直接序列化行对象,而不是父对象列表<代码>位置
甚至会写入输出
不知道从这里到哪里去
编辑3
经过一天的挖掘和尝试,上述c#和VB.NET代码之间的差异最终成为刷新XML编写器的一个问题。奇怪的是,C#代码不要求我在序列化对象后调用Flush()
,而VB.NET仅在WriteObject()之后调用Flush()
时才生成输出
我发现的另一件事是,IgnoreDataMember
对派生类中被重写的成员没有任何影响。必须在基类中应用该属性才能使其工作,这在我的例子中当然是不可能的。我想我必须发明一些破解方法来解决这个问题。必须使用“KnownType”才能使DataContractSerializer执行正确的序列化,因此您的基类需要DataContract Atibute并通知子类类型,如示例所示
[DataContract]
[KnownType(typeof(Label))]
public abstract class DrawingObject
{
public abstract string Location { get; set; }
public abstract string Size { get; set; }
}
“如果我没有用DataContract标记任何类,则IgnoreDataMember无效”-t尝试一下。我是在应用DataContract
之前这样做的<代码>位置
和大小
正在写入序列化输出。不应该发生这种情况。请阅读并创建一个“如果我没有用DataContract标记任何类,IgnoreDataMember无效”-您的意思是,您将该属性放在覆盖上?还是基于抽象属性?根据要求,请扩展到a。我仅在派生类上应用IgnoreDataMember
,显然不在基类中,因为我不希望它在标签
的情况下忽略这些属性。谢谢。我已经试过了。没什么区别。你成功地完成了吗?
[DataContract]
[KnownType(typeof(Label))]
public abstract class DrawingObject
{
public abstract string Location { get; set; }
public abstract string Size { get; set; }
}