让我们假设我必须在级别中序列化类Car的对象,例如内部和公共。公共级别中的某些属性不应序列化,因为它们是内部的。
此时我能想到的“最简单”的方法是使用继承:
class CarPublic {
public int PropX {get;set}
}
class CarInternal: CarPublic {
public string PropY {get;set}
}
然后我可以
object ToSerialize() {
CarInternal car = GetCar();
if( level == Level.Public ) {
return car as CarPublic;
} else {
return car;
}
}
ToSerialize()的结果是由一个框架(我没有 控制)并序列化为JSON或XML。
为简单起见,我省略了XML序列化属性。
这感觉就像一个黑客,黑客只带你到目前为止。有没有更好的方法(方式?)来实现这个目标?
我认为现在很清楚,但我想避免为JSON和XML编写自己的序列化方法。
提前致谢 Tymek
== EDIT
为了澄清,我希望能够序列化多个级别:
class Car0 {
public int PropA {get;set}
}
class Car1: Car0 {
public string PropB {get;set}
}
class Car2: Car1 {
public int PropC {get;set}
}
class Car3: Car2 {
public string PropD {get;set}
}
和
object ToSerialize( Level level ) {
Car3 car = GetCar();
switch( level ) {
case Level.Zero: return car as Car0;
case Level.One: return car as Car1;
case Level.Two: return car as Car3;
case Level.Three: return car as Car4;
}
return null;
}
==选择方法
我将Marc Gravell的答案标记为答案,因为它提供了C#及其“标准”组件如何支持我所要求的一般信息。
但是我认为我的问题的最佳方法是使用如上所示的代理类 让这个类在这个多级模式中被序列化,方法如下所示。
public interface ICar {
Car0 As0();
Car1 As1();
Car2 As2();
Car3 As3();
...
}
这样可以保持 Car0..3 类非常简单,只需要维护和理解属性。
答案 0 :(得分:5)
这很大程度上取决于您使用的序列化框架。你提到xml和json - 首先要注意的是你可以装饰:
[XmlIgnore]
public int PropX {get;set;}
或
[ScriptIgnore]
public int PropX {get;set;}
XmlSerializer
和JavascriptSerializer
会响应。如果您需要基于每个实例做出决策,则会有ShouldSerialize*
和*Specified
模式:
public bool ShouldSerializePropX() {
// return true to serialize, false to omit
}
以上是基于名称的模式,由XmlSerializer
和其他人使用;它有一个双胞胎:
[XmlIgnore, Browsable(false)]
public bool PropXSpecified {
get { /* return true to serialize, false to omit */ }
set { /* can just drop this value - don't need to assign */ }
}
你不需要做任何事情来连接它们 - 它们会自动工作。
不同的序列化程序允许不同的模式。
此外,有时您可以在运行时添加[XmlIgnore]
之类的内容 - 例如通过XmlAttributeOverrides
或任何给定序列化程序的等效项。
答案 1 :(得分:0)
您可以使用自定义属性修饰内部属性,指明应将其包含在内(或根据您的要求进行忽略),然后在ToSerialize
中检查属性。
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class ShouldSerializeAttribute : Attribute { }
然后你得到的类定义如下:
class Car
{
[ShouldSerialize]
public int PropX {get;set}
// This property won't be serialized because it is internal
public int PropY { get; set; }
}
你ToSerialize
看起来像是:
object ToSerialize()
{
Car car = GetCar();
foreach(PropertyInfo propInfo in car.GetType().GetProperties())
{
if(ShouldSerialize(propInfo))
{
return car;
}
}
}
ShouldSerialize
的位置如下:
internal bool ShouldSerialize(PropertyInfo propInfo)
{
return propInfo.GetCustomAttributes(typeof(ShouldSerializeAttribute), true).FirstOrDefault() != null;
}
<强>更新强>
基于@Bill对评论的见解。如果您希望仅在level
为Level.Public
时序列化公共属性,则可以通过使用BindingFlags.DeclaredOnly
标记反映类型的属性来实现此效果:
foreach(PropertyInfo propInfo in car.GetType().GetProperties(BindingFlags.DeclaredOnly))
这应返回仅由当前car
实例声明的属性列表。