强制子类必须在.net

时间:2018-12-14 14:18:19

标签: .net vb.net serialization

我在vb.net Web API中有一个类,有时需要序列化。因此,我将该班级标记为<Serializable>。精细。但是,它在许多级别上都有许多子类。其中一些被遗漏了(或由于添加了新的而被遗漏了)。如果该元素为null,那很好,但是如果不是,那么序列化将失败:

  

[SerializationException]在程序集“ Foo”中键入“ Foo.Bar”,   版本= 1.0.0.4866,文化=中性,PublicKeyToken =空'不是   标记为可序列化。

由于序列化是在后台使用的,因此为了保存状态以便以后恢复,并非总是会立即注意到它。

序列化正在vb.net中使用BinaryFormatter

有没有办法标记父类,使得所有子类(及其子类,等等)也必须可序列化?我宁愿为此遇到编译时错误,而不是运行时错误。

我从一些最初的答复中意识到,我的问题还不够清楚。我不应该使用 parents children 这两个词,因为我不太关注作为类成员继承的类

<Serializable()>
Class MyObj
  Public Property foo as new Foo
  Public Property bar as new Bar
end Class

我曾期望这会要求FooBar可序列化,因为否则MyObj 不是

3 个答案:

答案 0 :(得分:6)

不,您不能简单地强制执行此操作。最好的选择是添加一个单元测试,该单元测试通过反射来发现子类并检查它们是否具有属性,如果缺少该属性,则失败。

但是,我也建议不要使用BinaryFormatter 。我见过 way 太多的人为此受了伤害-它将类型和序列化数据紧密地联系在一起。 .NET中有很多更好的序列化选项,适用于基于文本和二进制的序列化格式。

答案 1 :(得分:1)

在VB.NET中,没有办法让派生类从其基类继承属性,更不用说强制它了。 .NET也无法在运行时动态地向类添加属性。另外,BinaryFormatter无法覆盖它,因此它可以序列化不可序列化的类型或强制其在基类中搜索属性。因此,您别无选择。以下是一些替代方法:

  • 如Mark所说,请勿使用BinaryFormatter。还有许多其他更好,更多的标准串行器,它们没有相同的限制。
  • 也如Mark所说,添加一个单元测试或其他一些后生成操作,如果任何派生类都忽略了该属性,则会导致生成失败
  • 在基类中用ISerializable个成员实现MustOverride,从而强制每个派生类提供一个实现(当该类实现该接口时,BinaryFormatter将使用该接口来执行序列化即使班级没有SerializableAttribute
  • 绝对最后一种方法:序列化时,如果要序列化的对象不是具有SerializableAttribute的类型,则理论上可以动态声明一个新类,该类继承给定对象的类中的内容,不会覆盖任何内容,但会添加SerializableAttribute。然后,创建该运行时生成类型的新对象,将数据从原始对象动态复制到该新对象,然后序列化该副本。但是,这不仅是一个可怕的想法,而且可能很难使自动生成的类具有完全相同的名称(包括完整的程序集名称),以致BinaryFormatter会将其视为完全相同。类型。 BinaryFormatter非常脆弱,因此让它与动态创建的类型一起使用是不切实际甚至是不可能的,这不会令我感到震惊。

答案 2 :(得分:1)

据我所知,在这种情况下无法执行编译时错误。 另外,您可以使用Inherited的{​​{1}}属性。 创建您的自定义Serializable属性只是为了覆盖AttributeUsage值。并使用它代替Inherited

[Serializable]属性的内部实现:

[Serializable]

此处 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate, Inherited = false)] public sealed class SerializableAttribute : Attribute { // // Summary: // Initializes a new instance of the System.SerializableAttribute class. public SerializableAttribute(); } 设置为Inherited;这意味着派生类不能继承此属性。 只需覆盖此属性并使用您的自定义属性即可。

您还可以在运行时验证子类中某些属性的存在。

通过引发自定义异常,可以帮助您确定确切的错误。

false