我使用扩展对象设计模式的简化版本解决了这个问题。
步骤1)
首先,我创建了以下接口和抽象基类,分别供扩展和可扩展对象使用:
public interface IExtension
{
bool IsSerializable { get; }
}
public abstract class Extensible
{
public static bool ShouldSerializeExtensions = true;
public IExtension Extension { get; set; }
public bool ShouldSerializeExtension()
{
return ShouldSerializeExtensions &&
Extension != null &&
Extension.IsSerializable;
}
}
静态ShoulSerializeExtensions
标志允许我暂时启用或禁用整个扩展的序列化,而该IsSerializable
属性允许我创建根本不应该序列化的扩展。
注意:在序列化之前,我还需要提供我创建的所有具体扩展类型的列表。
第2步)
我让层次结构中的每个节点都继承自Extensible
并为每个节点创建了扩展类:
public class A : Extensible
{
List<B> b { get; set; }
C c { get; set; }
}
public class B : Extensible
{
int d { get; set; }
}
public class C : Extensible
{
List<int> e { get; set; }
}
public class ExtensionA : IExtension
{
bool IsSerializable { get { return true; } }
int extra { get; set; }
}
public class ExtensionB : IExtension
{
bool IsSerializable { get { return true; } }
float extra { get; set; }
void something();
}
public class ExtensionC : IExtension
{
bool IsSerializable { get { return true; } }
float extra { get; set; }
}
步骤 3)
我创建了一个工厂,以确保创建每个节点都附加了正确的扩展对象。
public static class Factory
{
public static A CreateA()
{
var a = new A();
a.Extension = new ExtensionA();
return a;
}
...
}
而且我还创建了扩展方法,使操作扩展更容易,而不必每次都转换为正确的类型。
public static class ExtensionUtils
{
public static ExtensionA GetExtension(this A a)
{
return a.Extension as ExtensionA;
}
...
}
例子)
一切就绪后,我可以创建一个扩展对象并更改其值,如下所示:
var a = Factory.CreateA();
a.GetExtension().extra = 20;
而且我可以通过Extensible.ShouldSerializeExtensions
在序列化之前设置全局标志来序列化带有或不带有扩展名的层次结构。