I have a class in a vb.net web API that I need to serialize sometimes. So, i marked the class as <Serializable>
. Fine. However, it has a number of sub-classes at many levels. Some of these got missed (or gwet missed as new ones are added). If the element is null it's fine, but if it's not then the serialization fails:
[SerializationException] Type 'Foo.Bar' in Assembly 'Foo, Version=1.0.0.4866, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
Since the serialisation is used in the background, to save a sate to recover to later, it's not always noticed immediately.
Serialization is using the BinaryFormatter
in vb.net
Is there any way to mark the parent class such that all it's children (and their children, and so on) must also be serializable? I would prefer to get a compile-time error for this, rather than a run-time error.
I realised from some of the initial responses that my question wasn't clear enough. I should not have used the words parents and children since I am not so much focussed on class that inherit as members of the class
<Serializable()>
Class MyObj
Public Property foo as new Foo
Public Property bar as new Bar
end Class
I had expected this would require Foo
and Bar
to be serializable, since otherwise MyObj
isn't
Yes. Subclass need not be marked serializable explicitly.
If the superclass is Serializable, then by default, every subclass is serializable. Hence, even though subclass doesn't implement Serializable interface( and if its superclass implements Serializable), then we can serialize subclass object.
It's a little bit philosophical but by convention the default type of a class is not serializable, unless you explicitely define "this class can be serialized".
If you are curious to know if a Java Standard Class is serializable or not, check the documentation for the class. The test is simple: If the class implements java. io. Serializable, then it is serializable; otherwise, it's not.
No, that isn't something you can enforce simply. Your best bet may be to add a unit test that discovers the subclasses via reflection and checks whether they have the attribute, failing if it is missing.
However, I would also advise don't use BinaryFormatter
. I've seen way too many people get hurt by that - it ties the types and serialized data together too tightly. There are lots of better serialization options in .NET, for both text-based and binary serialization formats.
There is no way in VB.NET to have derived classes inherit the attributes from their base class, let alone force it. There is no way in .NET to add an attribute to a class dynamically at run-time either. Also, the BinaryFormatter
provides no way to override it such that it can serialize non-serializable types or to force it to search for the attribute in the base classes. So, you are left with no easy options. Here are some alternatives:
BinaryFormatter
. There are many other better and more standard serializers which do not have the same limitations.ISerializable
with MustOverride
members in the base class, thereby forcing each derived class to provide an implementation (when the class implements that interface, BinaryFormatter
will use that to perform the serialization even if the class doesn't have the SerializableAttribute
)SerializableAttribute
, you could theoretically declare a new class, dynamically, which inherits from the given object's class, overrides nothing, but adds the SerializableAttribute
. Then, create a new object of that run-time generated type, dynamically copy the data from the original one to that new one, and then serialize the copy. However, not only is this a terrible idea, it would probably be difficult to get the auto-generated class to have the exact same name (including the full assembly name) such that the BinaryFormatter
would see it as the same exact type. The BinaryFormatter
is exceptionally brittle, so it wouldn't shock me if it's impractical or even impossible to get it to work with dynamically created types.AS per my knowledge, there is no way to enforce compile time error in this case.
Alternative to this you can use Inherited
Property of AttributeUsage
.
Create your custom Serializable attribute just to override the Inherited
value. And use that instead of [Serializable]
.
Internal Implementation of [Serializable]
attribute:
[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();
}
Here Inherited
is set to false
; it means this attribute can not be inherited by derived class.
Just override this property and use your custom attribute.
You can also verify the existence of certain attributes in your sub classes at run time.
By throwing custom exception will help you to identify the exact error.
class BaseClass
{
public BaseClass()
{
Type t = GetType();
if (t.IsDefined(typeof(SerializableAttribute), false) == false)
{
Console.WriteLine("Serializable attribute is missing on class");
throw new InvalidOperationException("Serializable attribute is missing on class");
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With