-
-
Notifications
You must be signed in to change notification settings - Fork 3
Source Generators
Cesil supports generating serializers and deserializers at compile time using Source Generators. This requires adding the Cesil.SourceGenerator package, and adding annotations to (de)serialized types. While using Source Generators does allow for runtime code generation to be avoided, reflection is still necessary to find the generated code.
To use a compile time generated (de)serializer, use the AheadOfTimeTypeDescriber
on the Options
provided to Configuration
. A pre-allocated instance of AheadOfTimeTypeDescriber
can be found on TypeDescribers
.
To generate a serializer for a type, you must attach a GenerateSerializerAttribute
to it. The default behavior matches DefaultTypeDescriber
- that is that by default public properties with default formatters, and getters will be serialized. You can suppress this behavior by placing IgnoreDataMemberAttribute
on these properties.
To include fields, methods, or non-public properties you must use place DataMemberAttribute
or SerializerMemberAttribute
on the target member.
SerializerMemberAttribute
allows for setting explicit names, orders, formatters, and should serializers. Each of these options corresponds to an equivalent behavior of SerializableMembers
, which control runtime behavior.
Unlike with direct use of SerializableMember
, you cannot provide a delegate for any option. You also cannot provide any members that are not accessible from within the current assembly - in practice this means only public members, internal members in the current assembly, and internal members in assembly with an appropriate InternalsVisibleToAttribute
can be used.
When specify a related member (such as as a formatter), you must specify both a type and member name. For example, to specify a custom formatter you would write [SerializerMemberAttribute(FormatterType = typeof(MyType), FormatterMethodName = nameof(MyType.MyFormatter))]
.
Any accesible member of a type that could be used for a Formatter
or ShouldSerialize
at runtime may be used at compile time, the same parameter lists and return types are permitted.
To generate a deserializer for a type, you must attach a GenerateDeserializerAttribute
to it. The default behavior matches DefaultTypeDescriber
- that is that by default public properties with default parsers, and setters will be serialized. You can suppress this behavior by placing IgnoreDataMemberAttribute
on these properties.
To include fields, methods, or non-public properties you must use place DataMemberAttribute
or DeserializerMemberAttribute
on the target member.
Obtaining instances of a deserialized type my be customized by specifying a method on GenerateDeserializerAttribute
with the InstanceProviderType
and InstanceProviderMethodName
properties set. The method must conform to same style expected by InstanceProviders
in terms of parameter and return types, and must be accessible from the current assembly. To use a constructor (besides the parameterless constructor) to obtain types, you can attach the DeserializerInstanceProviderAttribute
to it. If you use a constructor with parameters as an instance provider, every parameter to it must be annotated with a DeserializerMemberAttribute
.
DeserializerMemberAttribute
allows for setting explicit names, orders, parsers, and resets. Each of these options corresponds to an equivalent behavior of DeserializableMembers
, which control runtime behavior.
Unlike with direct use of DeserializableMember
, you cannot provide a delegate for any option. You also cannot provide any members that are not accessible from within the current assembly - in practice this means only public members, internal members in the current assembly, and internal members in assembly with an appropriate InternalsVisibleToAttribute
can be used.
When specify a related member (such as as a parser), you must specify both a type and member name. For example, to specify a custom parser you would write [DeserializerMemberAttribute(ParserType = typeof(MyType), ParserMethodName = nameof(MyType.MyFormatter))]
.
Any accesible member of a type that could be used for a Parser
or Reset
at runtime may be used at compile time, the same parameter lists and return types are permitted.