c# - 避免使用 DataContractSerializer 和继承重复自己 (DRY)

标签 c# datacontractserializer anti-patterns known-types

我正在尝试编写一个文件头,它是一个表示某些对象层次结构的 XML 字符串。

此层次结构在某些点包含子类型,例如类 Plant包含 Stem 类型的属性,但序列化后,Root值可以是 Stem 的任何子类的实例,例如LongStem , DryStemRottenStem 。另外,还有一个属性Collection<LeafBase> Leaves其项目可以是 LeafBase 的任何子类型,例如GreenLeaf , SweetLeaf

如果我只使用默认代码,DataContractSerializer 将给出一个运行时错误,提示“意外类型”,因为它需要类型为 Stem 的对象。并接收类型 DryStem相反,例如。

因此,一些研究很快让我找到了已知类型解决方案,这要求我包含一个包含目标类型的每个子类的数组(天知道有多少额外层)。

嗯,这对我来说听起来像是对 DRY 和 SRP 原则的严重违反,因为如果每次我添加一个子类,我都必须在我的源代码中寻找要更新的已知类型列表(这是霰弹枪手术反) -pattern,是该系统之前版本中最糟糕的特征之一)。

我已经看到了一种使用反射并获取已知类型列表的方法,但我猜这有点黑客(我不在乎),所以我的问题是:

What would be a good way to handle DataContractSerialization for a class whose object tree contains a lot of inheritance, regarding DRY and the known-type-list issue?

或者,如果有另一种类型安全的方法将对象序列化和反序列化为 XML 字符串,并且不受此问题的影响,那么这可能是一种选择。

最佳答案

如果我正确理解您的意思,您可以通过在运行时发现派生基类的所有类型来避免每次创建新子类型时重复声明子类型。

大致如下:

[KnownType("GetKnownTypes")]
public abstract class Foo
{
    public static Type[] GetKnownTypes()
    {
        Type currentType = MethodBase.GetCurrentMethod().DeclaringType;
        return currentType.Assembly.GetTypes()
                                   .Where(t => t.IsSubclassOf(currentType))
                                   .ToArray();
    }
}

这样您就可以在运行时设置所有已知类型,而无需在每个派生类型上复制 KnownTypes 属性。

编辑:

Could you suggest a way to get types from every assembly in solution instead of just the one where base class is declared?

假设您有一个 AppDomain 和程序集,您可以搜索 AppDomain.CurrentDomain.GetAssemblies(),这将迭代当前加载的所有程序集中的所有类型应用程序域:

public static Type[] GetKnownTypes()
{
    Type currentType = MethodBase.GetCurrentMethod().DeclaringType;
    return AppDomain.CurrentDomain.GetAssemblies()
                                  .SelectMany(x => x.DefinedTypes)
                                  .Where(x => x.IsSubclassOf(currentType))
                                  .ToArray();
}

关于c# - 避免使用 DataContractSerializer 和继承重复自己 (DRY),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30304477/

相关文章:

c# - Web API - 自关闭标记而不是 i :nil

.net - System.Runtime.Serialization.DataContractSerializer 线程安全吗?

anti-patterns - 馄饨代码 - 为什么是反模式?

c# - 预处理 C# - 检测方法

c# - 带参数的通用 Windows 平台命令

datacontractserializer - ServiceStack 的 TypeSerializer 是否有 OnDeserializing/OnDeserialized 等价物?

javascript - JS 模式提供函数名称作为字符串

javascript - "foo.bar"和 "foo['的区别吧']"在js中

c# - C# 中的 LINQ to XML。枚举没有结果?

c# - cshtml 标签中的使用条件