1using System.Collections;
11public static class Serializer
16 public static ISerializer<object?> Dynamic => DynamicSerializer.Singleton;
18 private static readonly Dictionary<Type, ISerializer> _reg =
new();
20 internal static readonly HashSet<string> Tags =
new()
22 "@int",
"@long",
"@double",
"@date",
"@time",
"@mod",
"@stream",
"@ref",
"@doc",
"@set",
"@object"
25 private static readonly CheckedSerializer<object> _object =
new();
26 private static readonly StringSerializer _string =
new();
27 private static readonly ByteSerializer _byte =
new();
28 private static readonly SByteSerializer _sbyte =
new();
29 private static readonly ShortSerializer _short =
new();
30 private static readonly UShortSerializer _ushort =
new();
31 private static readonly IntSerializer _int =
new();
32 private static readonly UIntSerializer _uint =
new();
33 private static readonly LongSerializer _long =
new();
34 private static readonly FloatSerializer _float =
new();
35 private static readonly DoubleSerializer _double =
new();
36 private static readonly DateOnlySerializer _dateOnly =
new();
37 private static readonly DateTimeSerializer _dateTime =
new();
38 private static readonly DateTimeOffsetSerializer _dateTimeOffset =
new();
39 private static readonly BooleanSerializer _bool =
new();
40 private static readonly ModuleSerializer _module =
new();
41 private static readonly StreamSerializer _stream =
new();
42 private static readonly DocumentSerializer<Document> _doc =
new();
43 private static readonly DocumentSerializer<NamedDocument> _namedDoc =
new();
44 private static readonly DocumentSerializer<Ref> _docRef =
new();
45 private static readonly DocumentSerializer<NamedRef> _namedDocRef =
new();
53 public static ISerializer<T> Generate<T>(
MappingContext context) where T : notnull
55 var targetType = typeof(T);
56 var ser = (ISerializer<T>)Generate(context, targetType);
66 public static ISerializer Generate(
MappingContext context, Type targetType)
68 if (_reg.TryGetValue(targetType, out var s))
return s;
69 if (targetType == typeof(
object))
return _object;
70 if (targetType == typeof(
string))
return _string;
71 if (targetType == typeof(
byte))
return _byte;
72 if (targetType == typeof(sbyte))
return _sbyte;
73 if (targetType == typeof(
short))
return _short;
74 if (targetType == typeof(ushort))
return _ushort;
75 if (targetType == typeof(
int))
return _int;
76 if (targetType == typeof(uint))
return _uint;
77 if (targetType == typeof(
long))
return _long;
78 if (targetType == typeof(
float))
return _float;
79 if (targetType == typeof(
double))
return _double;
80 if (targetType == typeof(DateOnly))
return _dateOnly;
81 if (targetType == typeof(DateTime))
return _dateTime;
82 if (targetType == typeof(DateTimeOffset))
return _dateTimeOffset;
83 if (targetType == typeof(
bool))
return _bool;
84 if (targetType == typeof(
Module))
return _module;
85 if (targetType == typeof(
Stream))
return _stream;
86 if (targetType == typeof(
Document))
return _doc;
88 if (targetType == typeof(
Ref))
return _docRef;
89 if (targetType == typeof(
NamedRef))
return _namedDocRef;
91 if (targetType.IsGenericType)
93 if (targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
95 var args = targetType.GetGenericArguments();
98 var inner = (ISerializer)Generate(context, args[0]);
99 var serType = typeof(NullableStructSerializer<>).MakeGenericType(
new[] { args[0] });
100 object? ser = Activator.CreateInstance(serType,
new[] { inner });
102 return (ISerializer)ser!;
105 throw new ArgumentException($
"Unsupported nullable type. Generic arguments > 1: {args}");
112 var argTypes = targetType.GetGenericArguments();
113 var valueType = argTypes[0];
114 var serType = typeof(NullableDocumentSerializer<>).MakeGenericType(
new[] { valueType });
115 object? ser = Activator.CreateInstance(serType);
116 return (ISerializer)ser!;
119 if (targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
121 var argTypes = targetType.GetGenericArguments();
122 var keyType = argTypes[0];
123 var valueType = argTypes[1];
125 if (keyType != typeof(
string))
126 throw new ArgumentException(
127 $
"Unsupported Dictionary key type. Key must be of type string, but was a {keyType}");
129 var valueSerializer = Generate(context, valueType);
131 var serType = typeof(DictionarySerializer<>).MakeGenericType(
new[] { valueType });
132 object? ser = Activator.CreateInstance(serType,
new[] { valueSerializer });
134 return (ISerializer)ser!;
137 if (targetType.GetGenericTypeDefinition() == typeof(List<>) || targetType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
139 var elemType = targetType.GetGenericArguments()[0];
140 var elemSerializer = Generate(context, elemType);
142 var serType = typeof(ListSerializer<>).MakeGenericType(
new[] { elemType });
143 object? ser = Activator.CreateInstance(serType,
new[] { elemSerializer });
145 return (ISerializer)ser!;
148 if (targetType.GetGenericTypeDefinition() == typeof(Page<>))
150 var elemType = targetType.GetGenericArguments()[0];
151 var elemSerializer = Generate(context, elemType);
153 var serType = typeof(PageSerializer<>).MakeGenericType(
new[] { elemType });
154 object? ser = Activator.CreateInstance(serType,
new[] { elemSerializer });
156 return (ISerializer)ser!;
159 if (targetType.IsGenericType && targetType.Name.Contains(
"AnonymousType"))
161 return DynamicSerializer.Singleton;
166 if (targetType.IsClass)
168 var info = context.
GetInfo(targetType);
169 return info.ClassSerializer;
172 throw new ArgumentException($
"Unsupported deserialization target type {targetType}");
181 public static ISerializer<T?> GenerateNullable<T>(
MappingContext context)
183 var targetType = typeof(T);
184 var ser = (ISerializer<T>)Generate(context, targetType);
185 return new NullableSerializer<T>(ser);
194 public static ISerializer GenerateNullable(
MappingContext context, Type targetType)
196 var inner = (ISerializer)Generate(context, targetType);
197 var serType = typeof(NullableSerializer<>).MakeGenericType(
new[] { targetType });
198 var ser = Activator.CreateInstance(serType,
new[] { inner });
200 return (ISerializer)ser!;
209 public static void Register(Type t, ISerializer s)
211 if (!_reg.TryAdd(t, s))
throw new ArgumentException($
"Serializer for type `{t}` already registered");
219 public static void Register<T>(ISerializer<T> s)
222 foreach (var i
in s.GetType().GetInterfaces())
224 if (!i.IsGenericType || i.GetGenericTypeDefinition() != typeof(ISerializer<>))
continue;
226 var t = i.GetGenericArguments()[0];
227 success = _reg.TryAdd(t, s);
228 if (!success)
throw new ArgumentException($
"Serializer for type `{t}` already registered");
232 if (!success)
throw new ArgumentException($
"Could not infer associated type for `{s.GetType()}`. Use Register(type, serializer).");
239 public static void Deregister(Type t)
241 if (_reg.ContainsKey(t)) _reg.Remove(t);
A class representing the mapping context to be used during serialization and deserialization.
MappingInfo GetInfo(Type ty, string? colName=null)
Gets the MappingInfo for a given Type.
Represents a module, a singleton object grouping related functionalities. Modules are serialized as @...
Represents a document that has a "name" instead of an "id". For example, a Role document is represent...
Represents a document ref that has a "name" instead of an "id". For example, a Role document referenc...
A class wrapping a non-null document returned by Fauna.
A class representing a null document returned by Fauna.
A wrapper class that allows Document and user-defined classes to be null references.
Represents a document ref.
Represents a Fauna stream token.