• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / FluentCommand / 23278216331

19 Mar 2026 03:19AM UTC coverage: 57.398% (+0.7%) from 56.658%
23278216331

push

github

pwelter34
Enable nullable and improve source generators

1403 of 3069 branches covered (45.72%)

Branch coverage included in aggregate %.

527 of 907 new or added lines in 58 files covered. (58.1%)

22 existing lines in 10 files now uncovered.

4288 of 6846 relevant lines covered (62.64%)

330.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.66
/src/FluentCommand.Generators/TypeAccessorWriter.cs
1
using FluentCommand.Generators.Models;
2

3
namespace FluentCommand.Generators;
4

5
public static class TypeAccessorWriter
6
{
7
    public static string Generate(EntityClass entityClass)
8
    {
9
        if (entityClass == null)
3!
NEW
10
            throw new ArgumentNullException(nameof(entityClass));
×
11

12
        var codeBuilder = new IndentedStringBuilder();
3✔
13
        codeBuilder
3✔
14
            .AppendLine("// <auto-generated />")
3✔
15
            .AppendLine("#nullable enable")
3✔
16
            .AppendLine();
3✔
17

18
        codeBuilder
3✔
19
            .Append("namespace ")
3✔
20
            .AppendLine(entityClass.EntityNamespace)
3✔
21
            .AppendLine("{")
3✔
22
            .IncrementIndent();
3✔
23

24
        WriteTypeAccessorClass(codeBuilder, entityClass);
3✔
25

26
        WriteRegistration(codeBuilder, entityClass);
3✔
27

28
        codeBuilder
3✔
29
            .DecrementIndent()
3✔
30
            .AppendLine("}"); // namespace
3✔
31

32
        return codeBuilder.ToString();
3✔
33
    }
34

35
    private static void WriteTypeAccessorClass(IndentedStringBuilder codeBuilder, EntityClass entity)
36
    {
37
        codeBuilder
3✔
38
            .Append("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"")
3✔
39
            .Append(ThisAssembly.Product)
3✔
40
            .Append("\", \"")
3✔
41
            .Append(ThisAssembly.InformationalVersion)
3✔
42
            .AppendLine("\")]")
3✔
43
            .Append("internal sealed class ")
3✔
44
            .Append(entity.EntityName)
3✔
45
            .AppendLine("GeneratedTypeAccessor : global::FluentCommand.Reflection.TypeAccessor")
3✔
46
            .AppendLine("{")
3✔
47
            .IncrementIndent();
3✔
48

49
        // static member accessor fields
50
        foreach (var prop in entity.Properties)
26✔
51
        {
52
            codeBuilder
10✔
53
                .Append("internal static readonly global::FluentCommand.Reflection.IMemberAccessor ")
10✔
54
                .Append(prop.PropertyName)
10✔
55
                .Append("Member = new ")
10✔
56
                .Append(prop.PropertyName)
10✔
57
                .AppendLine("MemberAccessor();");
10✔
58
        }
59

60
        codeBuilder.AppendLine();
3✔
61

62
        WriteConstructor(codeBuilder, entity);
3✔
63

64
        // nested member accessor classes
65
        foreach (var prop in entity.Properties)
26✔
66
        {
67
            WriteMemberAccessorClass(codeBuilder, entity, prop);
10✔
68
        }
69

70
        codeBuilder
3✔
71
            .DecrementIndent()
3✔
72
            .AppendLine("}") // class
3✔
73
            .AppendLine();
3✔
74
    }
3✔
75

76
    private static void WriteConstructor(IndentedStringBuilder codeBuilder, EntityClass entity)
77
    {
78
        codeBuilder
3✔
79
            .Append("public ")
3✔
80
            .Append(entity.EntityName)
3✔
81
            .AppendLine("GeneratedTypeAccessor()")
3✔
82
            .IncrementIndent()
3✔
83
            .Append(": base(")
3✔
84
            .Append("typeof(")
3✔
85
            .Append(entity.FullyQualified)
3✔
86
            .Append("), ");
3✔
87

88
        // TableName
89
        if (entity.TableName != null)
3✔
90
            codeBuilder.Append("\"").Append(entity.TableName).Append("\", ");
2✔
91
        else
92
            codeBuilder.Append("null, ");
1✔
93

94
        // TableSchema
95
        if (entity.TableSchema != null)
3✔
96
            codeBuilder.Append("\"").Append(entity.TableSchema).Append("\", ");
1✔
97
        else
98
            codeBuilder.Append("null, ");
2✔
99

100
        // Constructor func
101
        if (entity.InitializationMode == InitializationMode.ObjectInitializer)
3✔
102
            codeBuilder.Append("static () => new ").Append(entity.FullyQualified).Append("())");
2✔
103
        else
104
            codeBuilder.Append("null)");
1✔
105

106
        codeBuilder
3✔
107
            .AppendLine()
3✔
108
            .DecrementIndent();
3✔
109

110
        // Constructor body
111
        codeBuilder
3✔
112
            .AppendLine("{")
3✔
113
            .IncrementIndent();
3✔
114

115
        // Register members by property name
116
        foreach (var prop in entity.Properties)
26✔
117
        {
118
            codeBuilder
10✔
119
                .Append("RegisterMember(\"")
10✔
120
                .Append(prop.PropertyName)
10✔
121
                .Append("\", ")
10✔
122
                .Append(prop.PropertyName)
10✔
123
                .AppendLine("Member);");
10✔
124
        }
125

126
        // Register by column name where different from property name
127
        foreach (var prop in entity.Properties)
26✔
128
        {
129
            if (!string.Equals(prop.ColumnName, prop.PropertyName, StringComparison.Ordinal))
10✔
130
            {
131
                codeBuilder
2✔
132
                    .Append("RegisterMember(\"")
2✔
133
                    .Append(prop.ColumnName)
2✔
134
                    .Append("\", ")
2✔
135
                    .Append(prop.PropertyName)
2✔
136
                    .AppendLine("Member);");
2✔
137
            }
138
        }
139

140
        codeBuilder.AppendLine();
3✔
141

142
        // Register properties collection for default GetProperties() flags
143
        codeBuilder
3✔
144
            .AppendLine("RegisterProperties(")
3✔
145
            .IncrementIndent()
3✔
146
            .AppendLine("global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.Static | global::System.Reflection.BindingFlags.Instance,")
3✔
147
            .AppendLine("new global::FluentCommand.Reflection.IMemberAccessor[]")
3✔
148
            .AppendLine("{")
3✔
149
            .IncrementIndent();
3✔
150

151
        WritePropertyArray(codeBuilder, entity);
3✔
152

153
        codeBuilder
3✔
154
            .DecrementIndent()
3✔
155
            .AppendLine("});")
3✔
156
            .DecrementIndent();
3✔
157

158
        codeBuilder
3✔
159
            .DecrementIndent()
3✔
160
            .AppendLine("}") // constructor
3✔
161
            .AppendLine();
3✔
162
    }
3✔
163

164
    private static void WritePropertyArray(IndentedStringBuilder codeBuilder, EntityClass entity)
165
    {
166
        var index = 0;
3✔
167
        var count = entity.Properties.Count;
3✔
168

169
        foreach (var prop in entity.Properties)
26✔
170
        {
171
            codeBuilder.Append(prop.PropertyName).Append("Member");
10✔
172

173
            if (++index < count)
10✔
174
                codeBuilder.AppendLine(",");
7✔
175
            else
176
                codeBuilder.AppendLine();
3✔
177
        }
178
    }
3✔
179

180
    private static void WriteMemberAccessorClass(IndentedStringBuilder codeBuilder, EntityClass entity, EntityProperty prop)
181
    {
182
        codeBuilder
10✔
183
            .Append("private sealed class ")
10✔
184
            .Append(prop.PropertyName)
10✔
185
            .AppendLine("MemberAccessor : global::FluentCommand.Reflection.IMemberAccessor")
10✔
186
            .AppendLine("{")
10✔
187
            .IncrementIndent();
10✔
188

189
        // MemberType
190
        codeBuilder
10✔
191
            .Append("public global::System.Type MemberType => typeof(")
10✔
192
            .Append(prop.PropertyType)
10✔
193
            .AppendLine(");");
10✔
194

195
        // Name
196
        codeBuilder
10✔
197
            .Append("public string Name => \"")
10✔
198
            .Append(prop.PropertyName)
10✔
199
            .AppendLine("\";");
10✔
200

201
        // Column
202
        codeBuilder
10✔
203
            .Append("public string Column => \"")
10✔
204
            .Append(prop.ColumnName)
10✔
205
            .AppendLine("\";");
10✔
206

207
        // ColumnType
208
        if (prop.ColumnType != null)
10✔
209
            codeBuilder.Append("public string? ColumnType => \"").Append(prop.ColumnType).AppendLine("\";");
1✔
210
        else
211
            codeBuilder.AppendLine("public string? ColumnType => null;");
9✔
212

213
        // ColumnOrder
214
        if (prop.ColumnOrder.HasValue)
10!
NEW
215
            codeBuilder.Append("public int? ColumnOrder => ").Append(prop.ColumnOrder.Value.ToString()).AppendLine(";");
×
216
        else
217
            codeBuilder.AppendLine("public int? ColumnOrder => null;");
10✔
218

219
        // Boolean metadata
220
        codeBuilder
10✔
221
            .Append("public bool IsKey => ")
10✔
222
            .AppendLine(prop.IsKey ? "true;" : "false;");
10✔
223

224
        codeBuilder
10!
225
            .Append("public bool IsNotMapped => ")
10✔
226
            .AppendLine(prop.IsNotMapped ? "true;" : "false;");
10✔
227

228
        codeBuilder
10✔
229
            .Append("public bool IsDatabaseGenerated => ")
10✔
230
            .AppendLine(prop.IsDatabaseGenerated ? "true;" : "false;");
10✔
231

232
        codeBuilder
10✔
233
            .Append("public bool IsConcurrencyCheck => ")
10✔
234
            .AppendLine(prop.IsConcurrencyCheck ? "true;" : "false;");
10✔
235

236
        // ForeignKey
237
        if (prop.ForeignKey != null)
10!
NEW
238
            codeBuilder.Append("public string? ForeignKey => \"").Append(prop.ForeignKey).AppendLine("\";");
×
239
        else
240
            codeBuilder.AppendLine("public string? ForeignKey => null;");
10✔
241

242
        codeBuilder
10!
243
            .Append("public bool HasGetter => ")
10✔
244
            .AppendLine(prop.HasGetter ? "true;" : "false;");
10✔
245

246
        codeBuilder
10!
247
            .Append("public bool HasSetter => ")
10✔
248
            .AppendLine(prop.HasSetter ? "true;" : "false;");
10✔
249

250
        codeBuilder
10✔
251
            .Append("public bool IsRequired => ")
10✔
252
            .AppendLine(prop.IsRequired ? "true;" : "false;");
10✔
253

254
        // DisplayName
255
        var displayName = prop.DisplayName ?? prop.PropertyName;
10✔
256
        codeBuilder
10✔
257
            .Append("public string DisplayName => \"")
10✔
258
            .Append(displayName)
10✔
259
            .AppendLine("\";");
10✔
260

261
        // DataFormatString
262
        if (prop.DataFormatString != null)
10!
NEW
263
            codeBuilder.Append("public string? DataFormatString => \"").Append(prop.DataFormatString).AppendLine("\";");
×
264
        else
265
            codeBuilder.AppendLine("public string? DataFormatString => null;");
10✔
266

267
        codeBuilder.AppendLine();
10✔
268

269
        // GetValue
270
        if (prop.HasGetter)
10!
271
        {
272
            codeBuilder
10✔
273
                .AppendLine("public object? GetValue(object instance)")
10✔
274
                .IncrementIndent()
10✔
275
                .Append("=> ((")
10✔
276
                .Append(entity.FullyQualified)
10✔
277
                .Append(")instance).")
10✔
278
                .Append(prop.PropertyName)
10✔
279
                .AppendLine(";")
10✔
280
                .DecrementIndent();
10✔
281
        }
282
        else
283
        {
NEW
284
            codeBuilder
×
NEW
285
                .AppendLine("public object? GetValue(object instance)")
×
NEW
286
                .IncrementIndent()
×
NEW
287
                .Append("=> throw new global::System.InvalidOperationException(\"Property '")
×
NEW
288
                .Append(prop.PropertyName)
×
NEW
289
                .AppendLine("' does not have a getter.\");")
×
NEW
290
                .DecrementIndent();
×
291
        }
292

293
        codeBuilder.AppendLine();
10✔
294

295
        // SetValue
296
        if (prop.HasSetter)
10!
297
        {
298
            codeBuilder
10✔
299
                .AppendLine("public void SetValue(object instance, object? value)")
10✔
300
                .IncrementIndent()
10✔
301
                .Append("=> ((")
10✔
302
                .Append(entity.FullyQualified)
10✔
303
                .Append(")instance).")
10✔
304
                .Append(prop.PropertyName)
10✔
305
                .Append(" = (")
10✔
306
                .Append(prop.PropertyType)
10✔
307
                .AppendLine(")value!;")
10✔
308
                .DecrementIndent();
10✔
309
        }
310
        else
311
        {
NEW
312
            codeBuilder
×
NEW
313
                .AppendLine("public void SetValue(object instance, object? value)")
×
NEW
314
                .IncrementIndent()
×
NEW
315
                .Append("=> throw new global::System.InvalidOperationException(\"Property '")
×
NEW
316
                .Append(prop.PropertyName)
×
NEW
317
                .AppendLine("' does not have a setter.\");")
×
NEW
318
                .DecrementIndent();
×
319
        }
320

321
        codeBuilder
10✔
322
            .DecrementIndent()
10✔
323
            .AppendLine("}") // class
10✔
324
            .AppendLine();
10✔
325
    }
10✔
326

327
    private static void WriteRegistration(IndentedStringBuilder codeBuilder, EntityClass entity)
328
    {
329
        codeBuilder
3✔
330
            .Append("internal static class ")
3✔
331
            .Append(entity.EntityName)
3✔
332
            .AppendLine("TypeAccessorRegistration")
3✔
333
            .AppendLine("{")
3✔
334
            .IncrementIndent();
3✔
335

336
        using (codeBuilder.SuspendIndent())
3✔
337
            codeBuilder.AppendLine("#if NET5_0_OR_GREATER");
3✔
338

339
        codeBuilder.AppendLine("[global::System.Runtime.CompilerServices.ModuleInitializer]");
3✔
340

341
        using (codeBuilder.SuspendIndent())
3✔
342
            codeBuilder.AppendLine("#endif");
3✔
343

344
        codeBuilder
3✔
345
            .AppendLine("internal static void Register()")
3✔
346
            .AppendLine("{")
3✔
347
            .IncrementIndent()
3✔
348
            .AppendLine("global::FluentCommand.Reflection.TypeAccessor.Register(")
3✔
349
            .IncrementIndent()
3✔
350
            .Append("typeof(")
3✔
351
            .Append(entity.FullyQualified)
3✔
352
            .AppendLine("),")
3✔
353
            .Append("new ")
3✔
354
            .Append(entity.EntityName)
3✔
355
            .AppendLine("GeneratedTypeAccessor());")
3✔
356
            .DecrementIndent()
3✔
357
            .DecrementIndent()
3✔
358
            .AppendLine("}"); // method
3✔
359

360
        codeBuilder
3✔
361
            .DecrementIndent()
3✔
362
            .AppendLine("}"); // class
3✔
363
    }
3✔
364
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc