Skip to content

Commit 4f9efa4

Browse files
committed
Fixed array support
Stream support ImmutableDictionary support Performance improvements
1 parent 590ca37 commit 4f9efa4

35 files changed

+240
-109
lines changed

src/AutoFakerBinder.cs

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections;
33
using System.Collections.Concurrent;
44
using System.Collections.Generic;
@@ -128,28 +128,21 @@ internal static void PopulateMembers(object instance, AutoFakerContext context,
128128

129129
if (value != null)
130130
{
131-
try
131+
if (!member.IsReadOnly)
132132
{
133-
if (!member.IsReadOnly)
133+
member.Setter.Invoke(instance, value);
134+
}
135+
else
136+
{
137+
if (member.IsDictionary)
134138
{
135-
member.Setter.Invoke(instance, value);
139+
PopulateDictionary(value, instance, member);
136140
}
137-
else
141+
else if (member.IsCollection)
138142
{
139-
if (member.IsDictionary)
140-
{
141-
PopulateDictionary(value, instance, member);
142-
}
143-
else if (member.IsCollection)
144-
{
145-
PopulateCollection(value, instance, member);
146-
}
143+
PopulateCollection(value, instance, member);
147144
}
148145
}
149-
catch (Exception e)
150-
{ // TODO: get rid of this, deal with failing unit
151-
Console.WriteLine(e.ToString());
152-
}
153146
}
154147

155148
// Remove the current type from the type stack so siblings can be created
@@ -187,7 +180,7 @@ private static bool ShouldSkip(AutoMember autoMember, AutoFakerContext context)
187180
// Inline logic to count matching types in the stack.
188181
if (autoMember.CachedType.CacheKey is { } cacheKeyValue)
189182
{
190-
int typeCount = 0;
183+
var typeCount = 0;
191184
foreach (int type in typesStack)
192185
{
193186
if (type == cacheKeyValue)
@@ -352,9 +345,7 @@ private static IAutoFakerGenerator GetParameterGenerator(CachedType type, Cached
352345
ref readonly CachedField cachedField = ref cachedFields[i];
353346

354347
// Skip constants, delegates, and backing fields
355-
if (cachedField.FieldInfo.IsConstant() ||
356-
cachedField.IsDelegate ||
357-
cachedField.FieldInfo.Name.Contains("k__BackingField"))
348+
if (cachedField.FieldInfo.IsConstant() || cachedField.IsDelegate || cachedField.FieldInfo.Name.Contains("k__BackingField"))
358349
continue;
359350

360351
autoMembers.Add(new AutoMember(cachedField, cacheService, autoFakerConfig));
@@ -396,18 +387,43 @@ private static void PopulateCollection(object value, object parent, AutoMember m
396387

397388
object? instance = member.Getter(parent);
398389

399-
if (instance is IList {IsReadOnly: true})
400-
return;
390+
switch (instance)
391+
{
392+
case null:
393+
return;
394+
case Array destArray:
395+
{
396+
int itemsToCopy = Math.Min(destArray.Length, collection.Count);
397+
var i = 0;
398+
399+
400+
foreach (object? item in collection)
401+
{
402+
if (i >= itemsToCopy)
403+
break;
404+
405+
// Handles boxing/unboxing and element-type conversion internally
406+
destArray.SetValue(item, i++);
407+
}
408+
409+
return;
410+
}
411+
case IList {IsReadOnly: true}:
412+
return;
413+
}
401414

402415
CachedType[] argTypes = member.CachedType.GetAddMethodArgumentTypes();
403416
CachedMethod? addMethod = GetAddMethod(member.CachedType, argTypes);
404417

405-
if (instance == null || addMethod == null)
418+
if (addMethod == null)
406419
return;
407420

421+
var args = new object[1];
422+
408423
foreach (object? item in collection)
409424
{
410-
addMethod.Invoke(instance, [item]);
425+
args[0] = item; // boxing avoidance
426+
addMethod.Invoke(instance, args);
411427
}
412428
}
413429

src/AutoFaker{T}.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,14 @@ private AutoFakerContext CreateContext(string? ruleSets)
116116
/// </summary>
117117
/// <param name="ruleSets"></param>
118118
/// <returns></returns>
119-
private List<string> ParseRuleSets(string? ruleSets)
119+
private HashSet<string> ParseRuleSets(string? ruleSets)
120120
{
121121
if (string.IsNullOrWhiteSpace(ruleSets))
122122
{
123123
ruleSets = null;
124124
}
125125

126-
var validRuleSets = new List<string>();
126+
var validRuleSets = new HashSet<string>();
127127

128128
string[] ruleSetArray = ruleSets?.Split(',') ?? [currentRuleSet];
129129

@@ -162,7 +162,7 @@ private void PrepareCreate(AutoFakerContext context)
162162
context.GenerateName = null;
163163

164164
// Get the members that should not be set during construction
165-
List<string> memberNames = GetRuleSetsMemberNames(context);
165+
HashSet<string> memberNames = GetRuleSetsMemberNames(context);
166166

167167
foreach (string? memberName in TypeProperties.Keys)
168168
{
@@ -232,7 +232,7 @@ private void PrepareFinish(AutoFakerContext context)
232232
{
233233
var finalAutoMembers = new List<AutoMember>();
234234

235-
List<string> memberNames = GetRuleSetsMemberNames(context);
235+
HashSet<string> memberNames = GetRuleSetsMemberNames(context);
236236

237237
for (var i = 0; i < autoMembers.Count; i++)
238238
{
@@ -254,17 +254,15 @@ private void PrepareFinish(AutoFakerContext context)
254254
_finishInitialized = true;
255255
}
256256

257-
private List<string> GetRuleSetsMemberNames(AutoFakerContext context)
257+
private HashSet<string> GetRuleSetsMemberNames(AutoFakerContext context)
258258
{
259-
var members = new List<string>();
259+
var members = new HashSet<string>();
260260

261261
if (context.RuleSets == null)
262262
return members;
263263

264-
for (var i = 0; i < context.RuleSets.Count; i++)
264+
foreach (string ruleSetName in context.RuleSets)
265265
{
266-
string ruleSetName = context.RuleSets[i];
267-
268266
if (!Actions.TryGetValue(ruleSetName, out Dictionary<string, PopulateAction<TType>>? ruleSet))
269267
{
270268
continue;

src/Context/AutoFakerContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public sealed class AutoFakerContext
4949
/// <summary>
5050
/// The requested rule sets provided for the generate request.
5151
/// </summary>
52-
public List<string>? RuleSets;
52+
public HashSet<string>? RuleSets;
5353

5454
internal readonly Stack<int> TypesStack;
5555

src/Context/AutoFakerOverrideContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public sealed class AutoFakerOverrideContext
3737
/// <summary>
3838
/// The requested rule sets provided for the generate request.
3939
/// </summary>
40-
public List<string>? RuleSets { get; }
40+
public HashSet<string>? RuleSets { get; }
4141

4242
internal AutoFakerOverrideContext(AutoFakerContext generateContext)
4343
{

src/Extensions/TypeArrayExtension.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ internal static (CachedType?, GenericCollectionType?) GetTypeOfGenericCollection
2323
case "IImmutableList`1":
2424
case "ImmutableList`1":
2525
return (cachedType, GenericCollectionType.ImmutableList);
26+
case "ImmutableDictionary`2":
27+
return (cachedType, GenericCollectionType.ImmutableDictionary);
2628
case "SortedList`2":
2729
return (cachedType, GenericCollectionType.SortedList);
2830
case "Dictionary`2":

src/Generators/AutoFakerGeneratorFactory.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ internal static IAutoFakerGenerator CreateGenerator(AutoFakerContext context)
128128
return CreateGenericGenerator(CachedTypeService.ReadOnlyDictionaryGenerator.Value, keyType, valueType);
129129
}
130130
case GenericCollectionType.ImmutableDictionary:
131+
{
132+
CachedType keyType = generics[0];
133+
CachedType valueType = generics[1];
134+
135+
return CreateGenericGenerator(CachedTypeService.ImmutableDictionaryGenerator.Value, keyType, valueType);
136+
}
131137
case GenericCollectionType.Dictionary:
132138
case GenericCollectionType.SortedList:
133139
{

src/Generators/AutoFakerGeneratorMemberOverride.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Soenneker.Utils.AutoBogus.Generators;
88
internal sealed class AutoFakerGeneratorMemberOverride<TType, TValue> : AutoFakerGeneratorOverride
99
{
1010
private Type Type { get; }
11+
1112
private readonly CachedType _cachedType;
1213

1314
private string MemberName { get; }

src/Generators/Types/BoolGenerator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
namespace Soenneker.Utils.AutoBogus.Generators.Types;
55

6-
internal sealed class BoolGenerator
7-
: IAutoFakerGenerator
6+
internal sealed class BoolGenerator : IAutoFakerGenerator
87
{
98
object IAutoFakerGenerator.Generate(AutoFakerContext context)
109
{

src/Generators/Types/ByteGenerator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
namespace Soenneker.Utils.AutoBogus.Generators.Types;
55

6-
internal sealed class ByteGenerator
7-
: IAutoFakerGenerator
6+
internal sealed class ByteGenerator : IAutoFakerGenerator
87
{
98
object IAutoFakerGenerator.Generate(AutoFakerContext context)
109
{

src/Generators/Types/DataSets/Base/BaseDataSetGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ internal abstract class BaseDataSetGenerator : IAutoFakerGenerator
99
{
1010
public static bool TryCreateGenerator(AutoFakerContext? context, CachedType dataSetType, out BaseDataSetGenerator? generator)
1111
{
12-
generator = default;
12+
generator = null;
1313

1414
CachedType cachedDataSetType = context.CacheService.Cache.GetCachedType(typeof(DataSet));
1515

0 commit comments

Comments
 (0)