我有一个只包含数据的类层次结构。例如:
class A
{
List<B> b { get; set; }
C c { get; set; }
}
class B
{
int d { get; set; }
}
class C
{
List<int> e { get; set; }
}
使用XML和protobuf-net准备类层次结构以进行序列化。它也存在于一个单独的库中,因为它需要由两个不同的应用程序使用。
现在我需要创建此类层次结构的扩展版本,其中节点的数量及其关系是相同的,但每个节点中可以有额外的数据,方法或属性。例如:
class AA : A
{
int extra { get; set; }
}
class BB : B
{
float extra { get; set; }
void something();
}
class CC : C
{
float extra { get; set; }
}
我在上面看到的一个问题是,类之间的所有(继承)引用仍然使用原始层次结构中的类型,即List<B>
而不是List<BB>
,所以我必须转换为新的类型一直在。更大的问题是我还需要能够从扩展的层次结构化原始层次结构,当每个实例都是派生类型时,我无法做到这一点。
问题:有没有办法扩展完整的类层次结构,这样我就可以在某处拥有共享的纯数据对象模型,并且仍然能够在外部添加更多信息和行为而不会丢失原始结构?
答案 0 :(得分:3)
我认为你可以使用泛型做你想做的事。至少对于防止铸造的解决方案。 我还在考虑如何从扩展的序列化序列化原始层次结构。
您问题中的B,BB,C和CC类仍然相同。
首先是通用A类:
class A<BType, CType> where BType: B where CType: C {
List<BType> b { get; set;}
CType c { get; set;}
}
然后使用泛型A类的非泛型A类:
class A: A<B, C> {
}
和(非泛型)AA类也使用泛型A类:
class AA: A<BB, CC> {
int extra { get; set; }
}
答案 1 :(得分:0)
我使用 Extension Object 设计模式的简化版本解决了问题。
步骤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步)
我创建了一个 Factory ,以确保创建的每个节点都附加了正确的扩展对象。
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
标志,我可以使用或不使用扩展来序列化层次结构。