Fauna v10 .NET/C# Driver 0.2.0-beta
 
Loading...
Searching...
No Matches
DataContextBuilder.cs
Go to the documentation of this file.
1using System.Diagnostics;
2using System.Reflection;
3using Fauna.Mapping;
4using Fauna.Util;
5
6namespace Fauna.Linq;
7
8internal class DataContextBuilder<DB> where DB : DataContext
9{
10 public DB Build(Client client)
11 {
12 var dbType = typeof(DB);
13 const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
14 var colTypes = dbType.GetNestedTypes(flags).Where(IsColType).ToList();
15 var colProps = dbType.GetProperties(flags).Where(IsColProp).ToList();
16
17 foreach (var ty in colTypes)
18 {
19 ValidateColType(ty);
20 }
21
22 foreach (var p in colProps)
23 {
24 ValidateColProp(colTypes, p);
25 }
26
27 var colImpls = new Dictionary<Type, DataContext.ICollection>();
28 foreach (var ty in colTypes)
29 {
30 colImpls[ty] = (DataContext.ICollection)Activator.CreateInstance(ty)!;
31 var nameAttr = ty.GetCustomAttribute<DataContext.NameAttribute>();
32 var colName = nameAttr?.Name ?? ty.Name;
33 }
34
35 var db = (DB)Activator.CreateInstance(dbType)!;
36 db.Init(client, colImpls, new MappingContext(colImpls.Values));
37 return db;
38 }
39
40 private static bool IsColType(Type ty) =>
41 ty.GetInterfaces().Any(iface => iface == typeof(DataContext.ICollection));
42
43 private static void ValidateColType(Type ty)
44 {
45 var isGeneric = ty.IsGenericType;
46 var colDef = GetColBase(ty);
47
48 var errors = new List<string>();
49
50 if (isGeneric) errors.Add("Cannot be generic.");
51 if (colDef is null) errors.Add("Must inherit Collection<>.");
52
53 if (errors.Any())
54 {
55 throw new InvalidOperationException(
56 $"Invalid collection type: {string.Join(" ", errors)}");
57 }
58 }
59
60 private static bool IsColProp(PropertyInfo prop)
61 {
62 var getter = prop.GetGetMethod();
63
64 if (getter is null) return false;
65 if (getter.IsStatic) return false;
66
67 var retType = getter.ReturnType;
68 if (!IsColType(retType)) return false;
69
70 return true;
71 }
72
73 private static void ValidateColProp(List<Type> colTypes, PropertyInfo prop)
74 {
75 var nullCtx = new NullabilityInfoContext();
76 var nullInfo = nullCtx.Create(prop);
77 var getter = prop.GetGetMethod()!;
78 var retType = getter.ReturnType;
79
80 var returnsValidColType = colTypes.Contains(retType);
81 var isNullable = nullInfo.ReadState is NullabilityState.Nullable;
82
83 var errors = new List<string>();
84
85 if (!returnsValidColType) errors.Add("Must return a nested collection type.");
86 if (isNullable) errors.Add("Cannot be nullable.");
87
88 if (errors.Any())
89 {
90 throw new InvalidOperationException(
91 $"Invalid collection property: {string.Join(" ", errors)}");
92 }
93 }
94
95 // helpers
96
97 private static Type? GetColBase(Type ty) => ty.GetGenInst(typeof(DataContext.Collection<>));
98
99 private static Type GetDocType(Type ty)
100 {
101 var col = GetColBase(ty);
102 Debug.Assert(col is not null);
103 return col.GetGenericArguments()[0];
104 }
105}
Represents a client for interacting with a Fauna.
Definition Client.cs:14
A class representing the mapping context to be used during serialization and deserialization.