|
1 |
| -using System; |
| 1 | +using System; |
2 | 2 | using System.Collections;
|
3 | 3 | using System.Collections.Concurrent;
|
4 | 4 | using System.Collections.Generic;
|
@@ -128,28 +128,21 @@ internal static void PopulateMembers(object instance, AutoFakerContext context,
|
128 | 128 |
|
129 | 129 | if (value != null)
|
130 | 130 | {
|
131 |
| - try |
| 131 | + if (!member.IsReadOnly) |
132 | 132 | {
|
133 |
| - if (!member.IsReadOnly) |
| 133 | + member.Setter.Invoke(instance, value); |
| 134 | + } |
| 135 | + else |
| 136 | + { |
| 137 | + if (member.IsDictionary) |
134 | 138 | {
|
135 |
| - member.Setter.Invoke(instance, value); |
| 139 | + PopulateDictionary(value, instance, member); |
136 | 140 | }
|
137 |
| - else |
| 141 | + else if (member.IsCollection) |
138 | 142 | {
|
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); |
147 | 144 | }
|
148 | 145 | }
|
149 |
| - catch (Exception e) |
150 |
| - { // TODO: get rid of this, deal with failing unit |
151 |
| - Console.WriteLine(e.ToString()); |
152 |
| - } |
153 | 146 | }
|
154 | 147 |
|
155 | 148 | // 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)
|
187 | 180 | // Inline logic to count matching types in the stack.
|
188 | 181 | if (autoMember.CachedType.CacheKey is { } cacheKeyValue)
|
189 | 182 | {
|
190 |
| - int typeCount = 0; |
| 183 | + var typeCount = 0; |
191 | 184 | foreach (int type in typesStack)
|
192 | 185 | {
|
193 | 186 | if (type == cacheKeyValue)
|
@@ -352,9 +345,7 @@ private static IAutoFakerGenerator GetParameterGenerator(CachedType type, Cached
|
352 | 345 | ref readonly CachedField cachedField = ref cachedFields[i];
|
353 | 346 |
|
354 | 347 | // 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")) |
358 | 349 | continue;
|
359 | 350 |
|
360 | 351 | autoMembers.Add(new AutoMember(cachedField, cacheService, autoFakerConfig));
|
@@ -396,18 +387,43 @@ private static void PopulateCollection(object value, object parent, AutoMember m
|
396 | 387 |
|
397 | 388 | object? instance = member.Getter(parent);
|
398 | 389 |
|
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 | + } |
401 | 414 |
|
402 | 415 | CachedType[] argTypes = member.CachedType.GetAddMethodArgumentTypes();
|
403 | 416 | CachedMethod? addMethod = GetAddMethod(member.CachedType, argTypes);
|
404 | 417 |
|
405 |
| - if (instance == null || addMethod == null) |
| 418 | + if (addMethod == null) |
406 | 419 | return;
|
407 | 420 |
|
| 421 | + var args = new object[1]; |
| 422 | + |
408 | 423 | foreach (object? item in collection)
|
409 | 424 | {
|
410 |
| - addMethod.Invoke(instance, [item]); |
| 425 | + args[0] = item; // boxing avoidance |
| 426 | + addMethod.Invoke(instance, args); |
411 | 427 | }
|
412 | 428 | }
|
413 | 429 |
|
|
0 commit comments