| Severity | Error |
| Reported by | Metalama.Framework |
| Message | Cannot generate a compile-time serializer for '<Type>' because the base type '<BaseType>' is not compile-time serializable and does not have a public or protected parameterless constructor. Make '<BaseType>' implement ICompileTimeSerializable, or add a public or protected parameterless constructor to it. |
Cause
When Metalama builds the compile-time code of a project, it generates a serializer and a deserializing constructor for every type that implements ICompileTimeSerializable and doesn't have a manual serializer. When the base type of such a type isn't itself serializable, Metalama doesn't serialize the state of the base type, and the generated deserializing constructor calls the parameterless constructor of the base type.
Metalama reports LAMA0205 when the type <Type> implements ICompileTimeSerializable but its base type <BaseType> doesn't, and <BaseType> has no public or protected parameterless constructor.
In the following example, the LogCategory class is serializable, but its base class NamedItem isn't, and the only constructor of NamedItem requires a name.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Serialization;
3
4namespace Doc.LAMA0205.Error;
5
6[RunTimeOrCompileTime]
7public class NamedItem
8{
9 public string Name { get; }
10
11 public NamedItem( string name )
12 {
13 this.Name = name;
14 }
15}
16
17// Error: the base type NamedItem is not serializable and has no parameterless constructor.
18[RunTimeOrCompileTime]
Error LAMA0205: Cannot generate a compile-time serializer for 'LogCategory' because the base type 'NamedItem' is not compile-time serializable and does not have a public or protected parameterless constructor. Make 'NamedItem' implement ICompileTimeSerializable, or add a public or protected parameterless constructor to it.
19public class LogCategory : NamedItem, ICompileTimeSerializable
20{
21 public int Level { get; }
22
23 public LogCategory( string name, int level ) : base( name )
24 {
25 this.Level = level;
26 }
27}
28
Resolution
Do one of the following:
- Make the base type implement ICompileTimeSerializable, so that Metalama also serializes its fields and properties. This is usually the right fix when the base type has state, like the
Nameproperty in the example. - Add a public or protected parameterless constructor to the base type. After deserialization, the fields and properties of the base type then have the values set by this constructor, not the serialized ones.
- If you can't change the base type, write a manual serializer for the derived type, as described in Serialization of aspects and other compile-time classes.
In the following example, NamedItem implements ICompileTimeSerializable.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Serialization;
3
4namespace Doc.LAMA0205.Fixed;
5
6// Fixed: the base type is now compile-time serializable, so its Name property is serialized too.
7[RunTimeOrCompileTime]
8public class NamedItem : ICompileTimeSerializable
9{
10 public string Name { get; }
11
12 public NamedItem( string name )
13 {
14 this.Name = name;
15 }
16}
17
18[RunTimeOrCompileTime]
19public class LogCategory : NamedItem, ICompileTimeSerializable
20{
21 public int Level { get; }
22
23 public LogCategory( string name, int level ) : base( name )
24 {
25 this.Level = level;
26 }
27}
28