Serialization Constructor¶
What does this mean ?¶
Legacy ISerializable types use a constructor accepting SerializationInfo and StreamingContext. The conventional accessibility is protected for an unsealed type and private for a sealed type. CA2229 is a legacy design rule, removed in .NET 8 because it conflicts with formatter deprecation diagnostics.
What can happen ?¶
Deserialization may bypass initialization performed by ordinary constructors. Missing validation can create invalid domain state. Constructor visibility is not an authorization boundary, and adding FileIOPermission demands does not secure modern .NET: Code Access Security is obsolete.
Recommendation¶
Prefer a supported format such as JSON with an explicit data model, bounded input, and validation after parsing. Do not introduce formatter serialization to satisfy this legacy rule. BinaryFormatter cannot be made safe for untrusted input by validating a field or changing constructor accessibility.
Sample Code¶
These are alternative constructor fragments inside an existing unsealed ISerializable type with an integer Count property. Its ordinary constructor applies the same 0..1000 invariant.
Missing invariant check:
protected LegacyRecord(SerializationInfo info, StreamingContext context)
{
Count = info.GetInt32("count");
}
Legacy maintenance only; not a safe deserialization format:
protected LegacyRecord(SerializationInfo info, StreamingContext context)
{
int count = info.GetInt32("count");
if (count < 0 || count > 1000)
throw new SerializationException("Invalid count");
Count = count;
}
Regression test: use a test subclass to exercise valid boundary values and reject -1, 1001, and a missing field. Test the replacement parser separately for malformed and oversized input. These constructor tests do not establish that a legacy object graph is safe to deserialize.