确定在运行时序列化哪些属性

让我们假设我必须在级别中序列化Car类的对象,例如Internal和Public。 公共级别中的某些属性不应该序列化,因为它们是内部的。

在这个时候,我能想到的“最简单”的方法就是使用inheritance:

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

==编辑

为了澄清,我希望能够序列化多个级别:

 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类非常简单,只有属性,以维护和理解。

这很大程度上取决于您使用的序列化框架。 你提到xml和json – 首先要注意的是你可以装饰:

 [XmlIgnore] public int PropX {get;set;} 

要么

 [ScriptIgnore] public int PropX {get;set;} 

哪个XmlSerializerJavascriptSerializer将响应。 如果您需要基于每个实例做出决定,那么就有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 ,或任何给定的序列化程序的等效项。

您可以使用自定义属性来装饰您的内部属性,指示应该包含它们(或根据您的要求忽略它们),然后在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; } 

UPDATE

基于@Bill对评论的见解。 如果您希望仅在levelLevel.Public时序列化公共属性,则可以通过使用BindingFlags.DeclaredOnly标志反映类型的属性来实现该效果:

 foreach(PropertyInfo propInfo in car.GetType().GetProperties(BindingFlags.DeclaredOnly)) 

这应返回仅由当前car实例声明的属性列表。