Fauna v10 .NET/C# Driver 0.2.0-beta
 
Loading...
Searching...
No Matches
Serializer.cs
Go to the documentation of this file.
1using System.Collections;
2using Fauna.Mapping;
3using Fauna.Types;
5
6namespace Fauna.Serialization;
7
11public static class Serializer
12{
16 public static ISerializer<object?> Dynamic => DynamicSerializer.Singleton;
17
18 private static readonly Dictionary<Type, ISerializer> _reg = new();
19
20 internal static readonly HashSet<string> Tags = new()
21 {
22 "@int", "@long", "@double", "@date", "@time", "@mod", "@stream", "@ref", "@doc", "@set", "@object"
23 };
24
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();
46
53 public static ISerializer<T> Generate<T>(MappingContext context) where T : notnull
54 {
55 var targetType = typeof(T);
56 var ser = (ISerializer<T>)Generate(context, targetType);
57 return ser;
58 }
59
66 public static ISerializer Generate(MappingContext context, Type targetType)
67 {
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;
87 if (targetType == typeof(NamedDocument)) return _namedDoc;
88 if (targetType == typeof(Ref)) return _docRef;
89 if (targetType == typeof(NamedRef)) return _namedDocRef;
90
91 if (targetType.IsGenericType)
92 {
93 if (targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
94 {
95 var args = targetType.GetGenericArguments();
96 if (args.Length == 1)
97 {
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 });
101
102 return (ISerializer)ser!;
103 }
104
105 throw new ArgumentException($"Unsupported nullable type. Generic arguments > 1: {args}");
106 }
107
108 if (targetType.GetGenericTypeDefinition() == typeof(NullableDocument<>) ||
109 targetType.GetGenericTypeDefinition() == typeof(NonNullDocument<>) ||
110 targetType.GetGenericTypeDefinition() == typeof(NullDocument<>))
111 {
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!;
117 }
118
119 if (targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
120 {
121 var argTypes = targetType.GetGenericArguments();
122 var keyType = argTypes[0];
123 var valueType = argTypes[1];
124
125 if (keyType != typeof(string))
126 throw new ArgumentException(
127 $"Unsupported Dictionary key type. Key must be of type string, but was a {keyType}");
128
129 var valueSerializer = Generate(context, valueType);
130
131 var serType = typeof(DictionarySerializer<>).MakeGenericType(new[] { valueType });
132 object? ser = Activator.CreateInstance(serType, new[] { valueSerializer });
133
134 return (ISerializer)ser!;
135 }
136
137 if (targetType.GetGenericTypeDefinition() == typeof(List<>) || targetType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
138 {
139 var elemType = targetType.GetGenericArguments()[0];
140 var elemSerializer = Generate(context, elemType);
141
142 var serType = typeof(ListSerializer<>).MakeGenericType(new[] { elemType });
143 object? ser = Activator.CreateInstance(serType, new[] { elemSerializer });
144
145 return (ISerializer)ser!;
146 }
147
148 if (targetType.GetGenericTypeDefinition() == typeof(Page<>))
149 {
150 var elemType = targetType.GetGenericArguments()[0];
151 var elemSerializer = Generate(context, elemType);
152
153 var serType = typeof(PageSerializer<>).MakeGenericType(new[] { elemType });
154 object? ser = Activator.CreateInstance(serType, new[] { elemSerializer });
155
156 return (ISerializer)ser!;
157 }
158
159 if (targetType.IsGenericType && targetType.Name.Contains("AnonymousType"))
160 {
161 return DynamicSerializer.Singleton;
162 }
163 }
164
165
166 if (targetType.IsClass)
167 {
168 var info = context.GetInfo(targetType);
169 return info.ClassSerializer;
170 }
171
172 throw new ArgumentException($"Unsupported deserialization target type {targetType}");
173 }
174
181 public static ISerializer<T?> GenerateNullable<T>(MappingContext context)
182 {
183 var targetType = typeof(T);
184 var ser = (ISerializer<T>)Generate(context, targetType);
185 return new NullableSerializer<T>(ser);
186 }
187
194 public static ISerializer GenerateNullable(MappingContext context, Type targetType)
195 {
196 var inner = (ISerializer)Generate(context, targetType);
197 var serType = typeof(NullableSerializer<>).MakeGenericType(new[] { targetType });
198 var ser = Activator.CreateInstance(serType, new[] { inner });
199
200 return (ISerializer)ser!;
201 }
202
209 public static void Register(Type t, ISerializer s)
210 {
211 if (!_reg.TryAdd(t, s)) throw new ArgumentException($"Serializer for type `{t}` already registered");
212 }
213
219 public static void Register<T>(ISerializer<T> s)
220 {
221 var success = false;
222 foreach (var i in s.GetType().GetInterfaces())
223 {
224 if (!i.IsGenericType || i.GetGenericTypeDefinition() != typeof(ISerializer<>)) continue;
225
226 var t = i.GetGenericArguments()[0];
227 success = _reg.TryAdd(t, s);
228 if (!success) throw new ArgumentException($"Serializer for type `{t}` already registered");
229 break;
230 }
231
232 if (!success) throw new ArgumentException($"Could not infer associated type for `{s.GetType()}`. Use Register(type, serializer).");
233 }
234
239 public static void Deregister(Type t)
240 {
241 if (_reg.ContainsKey(t)) _reg.Remove(t);
242 }
243}
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 document.
Definition Document.cs:7
Represents a module, a singleton object grouping related functionalities. Modules are serialized as @...
Definition Module.cs:8
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...
Definition NamedRef.cs:8
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.
Definition Ref.cs:7
Represents a Fauna stream token.
Definition Stream.cs:7
Definition Client.cs:8