diff --git a/.gitignore b/.gitignore
index 1ee5385..3413bc0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -360,3 +360,7 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
+
+# JetBrains Rider
+.idea/
+*.sln.iml
\ No newline at end of file
diff --git a/README.md b/README.md
index 09f27d5..9623e7c 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,13 @@
[![](https://img.shields.io/nuget/dt/soenneker.utils.autobogus.svg?style=for-the-badge)](https://www.nuget.org/packages/soenneker.utils.autobogus/)
# ![](https://user-images.githubusercontent.com/4441470/224455560-91ed3ee7-f510-4041-a8d2-3fc093025112.png) Soenneker.Utils.AutoBogus
-### The .NET Bogus autogenerator
+### The .NET Autogenerator
-This project is a replacement for the abandoned [AutoBogus](https://github.com/nickdodd79/AutoBogus) library. It's mostly plug and play. It aims to be fast, and support the latest types in .NET.
+This project is an automatic creator and populator for the fake data generator [Bogus](https://github.com/bchavez/Bogus).
+
+It's a replacement for the abandoned [AutoBogus](https://github.com/nickdodd79/AutoBogus) library. It's mostly plug and play.
+
+The goals are to be *fast*, and support the latest types in .NET.
.NET Standard 2.1 is required.
diff --git a/src/Abstract/IAutoFakerBinder.cs b/src/Abstract/IAutoFakerBinder.cs
index e1ae77c..aa03de6 100644
--- a/src/Abstract/IAutoFakerBinder.cs
+++ b/src/Abstract/IAutoFakerBinder.cs
@@ -1,3 +1,4 @@
+using System;
using System.Reflection;
using Bogus;
using Soenneker.Utils.AutoBogus.Context;
@@ -17,6 +18,8 @@ public interface IAutoFakerBinder : IBinder
/// The created instance.
TType? CreateInstance(AutoFakerContext context);
+ object? CreateInstance(AutoFakerContext context, Type type);
+
///
/// Populates the provided instance with generated values.
///
@@ -29,4 +32,6 @@ public interface IAutoFakerBinder : IBinder
/// values are applied to the provided instance and not a copy.
///
void PopulateInstance(object instance, AutoFakerContext context, MemberInfo[]? members = null);
+
+ void PopulateInstance(object instance, AutoFakerContext context, Type type, MemberInfo[]? members = null);
}
\ No newline at end of file
diff --git a/src/AutoFakerBinder.cs b/src/AutoFakerBinder.cs
index 899faa6..5aa653b 100644
--- a/src/AutoFakerBinder.cs
+++ b/src/AutoFakerBinder.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Data;
using System.Linq;
using System.Reflection;
using Soenneker.Reflection.Cache.Constructors;
@@ -50,6 +51,49 @@ public class AutoFakerBinder : Binder, IAutoFakerBinder
}
+ public object? CreateInstance(AutoFakerContext? context, Type type)
+ {
+ if (context == null)
+ return default;
+
+ CachedConstructor? constructor = GetConstructor(context.CachedType);
+
+ if (constructor == null)
+ return default;
+
+ ParameterInfo[] parametersInfo = constructor.GetParameters();
+ var parameters = new object[parametersInfo.Length];
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = GetParameterGenerator(type, parametersInfo[i], context).Generate(context);
+ }
+
+ return constructor.Invoke(parameters);
+ }
+
+ public virtual TType? CreateInstance(AutoFakerContext? context, Type type)
+ {
+ if (context == null)
+ return default;
+
+ CachedConstructor? constructor = GetConstructor(context.CachedType);
+
+ if (constructor == null)
+ return default;
+
+ ParameterInfo[] parametersInfo = constructor.GetParameters();
+ var parameters = new object[parametersInfo.Length];
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = GetParameterGenerator(type, parametersInfo[i], context).Generate(context);
+ }
+
+ return (TType?)constructor.Invoke(parameters);
+
+ }
+
///
/// Populates the provided instance with generated values.
///
@@ -120,6 +164,63 @@ public virtual void PopulateInstance(object? instance, AutoFakerContext?
}
}
+ public void PopulateInstance(object instance, AutoFakerContext context, Type type, MemberInfo[]? members = null)
+ {
+ // We can only populate non-null instances
+ if (instance == null || context == null)
+ {
+ return;
+ }
+
+ CachedType cachedType = CacheService.Cache.GetCachedType(type);
+
+ // Iterate the members and bind a generated value
+ List autoMembers = GetMembersToPopulate(cachedType, members);
+
+ foreach (AutoMember? member in autoMembers)
+ {
+ if (member.Type != null)
+ {
+ // Check if the member has a skip config or the type has already been generated as a parent
+ // If so skip this generation otherwise track it for use later in the object tree
+ if (ShouldSkip(member.Type, $"{type.FullName}.{member.Name}", context))
+ {
+ continue;
+ }
+
+ context.Setup(type, member.Type, member.Name);
+
+ context.TypesStack.Push(member.Type);
+
+ // Generate a random value and bind it to the instance
+ IAutoFakerGenerator generator = GeneratorFactory.GetGenerator(context);
+ object value = generator.Generate(context);
+
+ try
+ {
+ if (!member.IsReadOnly)
+ {
+ member.Setter.Invoke(instance, value);
+ }
+ else if (member.CachedType.IsDictionary())
+ {
+ PopulateDictionary(value, instance, member);
+ }
+ else if (member.CachedType.IsCollection())
+ {
+ PopulateCollection(value, instance, member);
+ }
+ }
+ catch
+ {
+ }
+
+ // Remove the current type from the type stack so siblings can be created
+ context.TypesStack.Pop();
+ }
+ }
+ }
+
private static bool ShouldSkip(Type type, string path, AutoFakerContext context)
{
// Skip if the type is found
diff --git a/src/AutoFaker[T].cs b/src/AutoFaker[T].cs
deleted file mode 100644
index 84dd1f5..0000000
--- a/src/AutoFaker[T].cs
+++ /dev/null
@@ -1,317 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using Bogus;
-using Soenneker.Utils.AutoBogus.Abstract;
-using Soenneker.Utils.AutoBogus.Extensions;
-using Soenneker.Utils.AutoBogus.Services;
-
-namespace Soenneker.Utils.AutoBogus;
-
-///
-/// A class used to invoke generation requests of type .
-///
-/// The type of instance to generate.
-public class AutoFaker
-{
- private AutoConfig _config;
-
- ///
- /// Instantiates an instance of the class.
- ///
- public AutoFaker()
- : this(null, null)
- {
- }
-
- ///
- /// Instantiates an instance of the class.
- ///
- /// The locale to use for value generation.
- public AutoFaker(string locale)
- : this(locale, null)
- {
- }
-
- ///
- /// Instantiates an instance of the class.
- ///
- /// The instance to use for the generation request.
- public AutoFaker(IAutoBinder binder)
- : this(null, binder)
- {
- }
-
- ///
- /// Instantiates an instance of the class.
- ///
- /// The locale to use for value generation.
- /// The instance to use for the generation request.
- public AutoFaker(string locale = null, IAutoBinder binder = null)
- : base(locale ?? AutoConfig.DefaultLocale, binder)
- {
- Binder = binder;
-
- // Ensure the default create action is cleared
- // This is so we can check whether it has been set externally
- DefaultCreateAction = CreateActions[currentRuleSet];
- CreateActions[currentRuleSet] = null;
- }
-
- ///
- /// The instance to use for the generation request.
- ///
- public IAutoBinder Binder { get; set; }
-
- internal AutoConfig Config
- {
- set
- {
- _config = value;
-
- Locale = _config.Locale;
- Binder = _config.Binder;
-
- // Also pass the binder set up to the underlying Faker
- binder = _config.Binder;
-
- if (FakerService.IsValueCreated)
- FakerHub = FakerService.Faker;
-
- // Apply a configured faker if set
- //if (_config.FakerHub != null)
- //{
- // FakerHub = _config.FakerHub;
- //}
- }
- }
-
- private bool CreateInitialized { get; set; }
- private bool FinishInitialized { get; set; }
- private Func DefaultCreateAction { get; set; }
-
- ///
- /// Configures the current faker instance.
- ///
- /// A handler to build the faker configuration.
- /// The current faker instance.
- public AutoFaker Configure(Action configure)
- {
- var config = new AutoConfig(AutoFaker.DefaultConfig);
-
- var builder = new AutoConfigBuilder(config);
-
- configure.Invoke(builder);
-
- Config = config;
-
- return this;
- }
-
- ///
- /// Generates an instance of type .
- ///
- /// An optional list of delimited rule sets to use for the generate request.
- /// The generated instance of type .
- public override TType Generate(string ruleSets = null)
- {
- AutoGenerateContext context = CreateContext(ruleSets);
-
- PrepareCreate(context);
- PrepareFinish(context);
-
- return base.Generate(ruleSets);
- }
-
- ///
- /// Generates a collection of instances of type .
- ///
- /// The number of instances to generate.
- /// An optional list of delimited rule sets to use for the generate request.
- /// The collection of generated instances of type .
- public override List Generate(int count, string ruleSets = null)
- {
- AutoGenerateContext context = CreateContext(ruleSets);
-
- PrepareCreate(context);
- PrepareFinish(context);
-
- return base.Generate(count, ruleSets);
- }
-
- ///
- /// Populates the provided instance with auto generated values.
- ///
- /// The instance to populate.
- /// An optional list of delimited rule sets to use for the populate request.
- public override void Populate(TType instance, string ruleSets = null)
- {
- AutoGenerateContext context = CreateContext(ruleSets);
- PrepareFinish(context);
-
- base.Populate(instance, ruleSets);
- }
-
- private AutoGenerateContext CreateContext(string ruleSets)
- {
- var config = new AutoConfig(_config ?? AutoFaker.DefaultConfig);
-
- if (!string.IsNullOrWhiteSpace(Locale))
- {
- config.Locale = Locale;
- }
-
- if (Binder != null)
- {
- config.Binder = Binder;
- }
-
- return new AutoGenerateContext(config)
- {
- RuleSets = ParseRuleSets(ruleSets)
- };
- }
-
- ///
- /// Parse and clean the rule set list
- /// If the rule set list is empty it defaults to a list containing only 'default'
- /// By this point the currentRuleSet should be 'default'
- ///
- ///
- ///
- private List ParseRuleSets(string? ruleSets)
- {
- if (string.IsNullOrWhiteSpace(ruleSets))
- {
- ruleSets = null;
- }
-
- List validRuleSets = new List();
-
- string[] ruleSetArray = ruleSets?.Split(',') ?? new[] {currentRuleSet};
-
- for (int i = 0; i < ruleSetArray.Length; i++)
- {
- string trimmedRuleSet = ruleSetArray[i].Trim();
-
- if (!string.IsNullOrWhiteSpace(trimmedRuleSet))
- {
- validRuleSets.Add(trimmedRuleSet);
- }
- }
-
- return validRuleSets;
- }
-
- private void PrepareCreate(AutoGenerateContext context)
- {
- // Check a create handler hasn't previously been set or configured externally
- if (!CreateInitialized && CreateActions[currentRuleSet] == null)
- {
- CreateActions[currentRuleSet] = faker =>
- {
- // Only auto create if the 'default' rule set is defined for generation
- // This is because any specific rule sets are expected to handle the full creation
- if (context.RuleSets.Contains(currentRuleSet))
- {
- Type type = typeof(TType);
-
- // Set the current type being generated
- context.ParentType = null;
- context.GenerateType = type;
- context.GenerateName = null;
-
- // Get the members that should not be set during construction
- List memberNames = GetRuleSetsMemberNames(context);
-
- foreach (string? memberName in TypeProperties.Keys)
- {
- if (memberNames.Contains(memberName))
- {
- var path = $"{type.FullName}.{memberName}";
- bool existing = context.Config.SkipPaths.Any(s => s == path);
-
- if (!existing)
- {
- context.Config.SkipPaths.Add(path);
- }
- }
- }
-
- // Create a blank instance. It will be populated in the FinalizeAction registered
- // by PrepareFinish (context.Binder.PopulateInstance).
- return context.Binder.CreateInstance(context);
- }
-
- return DefaultCreateAction.Invoke(faker);
- };
-
- CreateInitialized = true;
- }
- }
-
- private void PrepareFinish(AutoGenerateContext context)
- {
- if (FinishInitialized)
- return;
-
- FinalizeActions.TryGetValue(currentRuleSet, out FinalizeAction finishWith);
-
- FinishWith((faker, instance) =>
- {
- if (instance is not null && instance.GetType().IsExpandoObject())
- {
- context.ParentType = null;
- context.GenerateType = instance.GetType();
- context.GenerateName = null;
- context.Instance = instance;
-
- IAutoGenerator generator = AutoGeneratorFactory.GetGenerator(context);
- generator.Generate(context);
-
- context.Instance = null;
- return;
- }
-
- List memberNames = GetRuleSetsMemberNames(context);
-
- var members = new MemberInfo[TypeProperties.Count - memberNames.Count];
- var index = 0;
-
- foreach (KeyValuePair member in TypeProperties)
- {
- if (!memberNames.Contains(member.Key))
- {
- members[index++] = member.Value;
- }
- }
-
- context.Binder.PopulateInstance(instance, context, members.Where(m => m != null).ToArray());
-
- finishWith?.Action(faker, instance);
- });
-
- FinishInitialized = true;
- }
-
- private List GetRuleSetsMemberNames(AutoGenerateContext context)
- {
- var members = new List();
-
- for (int i = 0; i < context.RuleSets.Count; i++)
- {
- string? ruleSetName = context.RuleSets[i];
-
- if (Actions.TryGetValue(ruleSetName, out Dictionary>? ruleSet))
- {
- foreach (KeyValuePair> keyValuePair in ruleSet)
- {
- members.Add(keyValuePair.Key);
- }
- }
- }
-
- return members;
- }
-}
\ No newline at end of file
diff --git a/src/Config/AutoFakerConfig.cs b/src/Config/AutoFakerConfig.cs
index cd3f071..05f34e6 100644
--- a/src/Config/AutoFakerConfig.cs
+++ b/src/Config/AutoFakerConfig.cs
@@ -29,7 +29,7 @@ internal sealed class AutoFakerConfig
internal List SkipPaths { get; set; }
- internal List Overrides { get; set; }
+ internal List? Overrides { get; set; }
public Func TreeDepth { get; set; }
@@ -48,7 +48,10 @@ internal AutoFakerConfig()
SkipPaths = [];
Overrides = [];
- Faker ??= new Faker(Locale);
+ if (Faker != null)
+ return;
+
+ Faker = new Faker(Locale);
}
internal AutoFakerConfig(AutoFakerConfig fakerConfig)
@@ -64,6 +67,9 @@ internal AutoFakerConfig(AutoFakerConfig fakerConfig)
SkipPaths = fakerConfig.SkipPaths;
Overrides = fakerConfig.Overrides;
+ if (Faker != null)
+ return;
+
Faker = fakerConfig.Faker ?? new Faker(Locale);
}
}
\ No newline at end of file
diff --git a/src/Context/AutoFakerContext.cs b/src/Context/AutoFakerContext.cs
index 8ed0ea9..34c67e1 100644
--- a/src/Context/AutoFakerContext.cs
+++ b/src/Context/AutoFakerContext.cs
@@ -49,7 +49,7 @@ public sealed class AutoFakerContext
internal IAutoFakerBinder FakerBinder => AutoFakerConfig.FakerBinder;
- internal List Overrides => AutoFakerConfig.Overrides;
+ internal List? Overrides => AutoFakerConfig.Overrides;
internal AutoFakerContext(AutoFakerConfig autoFakerConfig, Type? type = null)
{
diff --git a/src/Extensions/TypeExtension.cs b/src/Extensions/TypeExtension.cs
index 9654220..ae4361e 100644
--- a/src/Extensions/TypeExtension.cs
+++ b/src/Extensions/TypeExtension.cs
@@ -1,7 +1,6 @@
using System;
using System.Dynamic;
using Soenneker.Reflection.Cache.Types;
-using Soenneker.Utils.AutoBogus.Services;
namespace Soenneker.Utils.AutoBogus.Extensions;
diff --git a/src/Generators/GeneratorFactory.cs b/src/Generators/GeneratorFactory.cs
index e37fb7a..b9dc142 100644
--- a/src/Generators/GeneratorFactory.cs
+++ b/src/Generators/GeneratorFactory.cs
@@ -20,6 +20,8 @@ internal static class GeneratorFactory
{typeof(char), new CharGenerator()},
{typeof(DateTime), new DateTimeGenerator()},
{typeof(DateTimeOffset), new DateTimeOffsetGenerator()},
+ {typeof(DateOnly), new DateOnlyGenerator()},
+ {typeof(TimeOnly), new TimeOnlyGenerator()},
{typeof(decimal), new DecimalGenerator()},
{typeof(double), new DoubleGenerator()},
{typeof(float), new FloatGenerator()},
@@ -40,23 +42,25 @@ internal static IAutoFakerGenerator GetGenerator(AutoFakerContext context)
{
IAutoFakerGenerator generator = ResolveGenerator(context);
- // Check if any overrides are available for this generate request
- var overrides = new List();
+ List? overrides = null;
- foreach (GeneratorOverride? o in context.Overrides)
+ if (context.Overrides != null)
{
- if (o.CanOverride(context))
+ overrides = [];
+
+ for (var i = 0; i < context.Overrides.Count; i++)
{
- overrides.Add(o);
+ GeneratorOverride? o = context.Overrides[i];
+
+ if (o.CanOverride(context))
+ overrides.Add(o);
}
}
- if (overrides.Count > 0)
- {
- return new GeneratorOverrideInvoker(generator, overrides);
- }
+ if (overrides == null || overrides.Count == 0)
+ return generator;
- return generator;
+ return new GeneratorOverrideInvoker(generator, overrides);
}
internal static IAutoFakerGenerator ResolveGenerator(AutoFakerContext context)
@@ -69,13 +73,6 @@ internal static IAutoFakerGenerator ResolveGenerator(AutoFakerContext context)
type = type.GetElementType();
}
- // Check if an expando object needs to generator
- // This actually means an existing dictionary needs to be populated
- if (context.CachedType.IsExpandoObject())
- {
- return new ExpandoObjectGenerator();
- }
-
// Do some type -> generator mapping
if (type.IsArray)
{
@@ -83,14 +80,10 @@ internal static IAutoFakerGenerator ResolveGenerator(AutoFakerContext context)
return CreateGenericGenerator(typeof(ArrayGenerator<>), type);
}
- if (DataTableGenerator.TryCreateGenerator(context.CachedType, out DataTableGenerator dataTableGenerator))
- {
- return dataTableGenerator;
- }
-
- if (DataSetGenerator.TryCreateGenerator(context.CachedType, out DataSetGenerator dataSetGenerator))
+ // Resolve the generator from the type
+ if (Generators.TryGetValue(type, out IAutoFakerGenerator? generator))
{
- return dataSetGenerator;
+ return generator;
}
if (context.CachedType.IsEnum)
@@ -104,60 +97,71 @@ internal static IAutoFakerGenerator ResolveGenerator(AutoFakerContext context)
return CreateGenericGenerator(typeof(NullableGenerator<>), type);
}
+ // Check if an expando object needs to generator
+ // This actually means an existing dictionary needs to be populated
+ if (context.CachedType.IsExpandoObject())
+ {
+ return new ExpandoObjectGenerator();
+ }
+
(CachedType? collectionType, GenericCollectionType? genericCollectionType) = GenericTypeUtil.GetGenericCollectionType(context.CachedType);
if (collectionType != null)
{
// For generic types we need to interrogate the inner types
- Type[] generics = collectionType.GetGenericArguments();
+ Type[] generics = collectionType.GetGenericArguments()!;
switch (genericCollectionType!.Name)
{
case nameof(GenericCollectionType.ReadOnlyDictionary):
- {
- Type keyType = generics[0];
- Type valueType = generics[1];
+ {
+ Type keyType = generics[0];
+ Type valueType = generics[1];
- return CreateGenericGenerator(typeof(ReadOnlyDictionaryGenerator<,>), keyType, valueType);
- }
+ return CreateGenericGenerator(typeof(ReadOnlyDictionaryGenerator<,>), keyType, valueType);
+ }
case nameof(GenericCollectionType.ImmutableDictionary):
case nameof(GenericCollectionType.Dictionary):
case nameof(GenericCollectionType.SortedList):
- {
- return CreateDictionaryGenerator(generics);
- }
+ {
+ return CreateDictionaryGenerator(generics);
+ }
case nameof(GenericCollectionType.ReadOnlyList):
case nameof(GenericCollectionType.ListType):
case nameof(GenericCollectionType.ReadOnlyCollection):
case nameof(GenericCollectionType.Collection):
- {
- Type elementType = generics[0];
- return CreateGenericGenerator(typeof(ListGenerator<>), elementType);
- }
+ {
+ Type elementType = generics[0];
+ return CreateGenericGenerator(typeof(ListGenerator<>), elementType);
+ }
case nameof(GenericCollectionType.Set):
- {
- Type elementType = generics[0];
- return CreateGenericGenerator(typeof(SetGenerator<>), elementType);
- }
+ {
+ Type elementType = generics[0];
+ return CreateGenericGenerator(typeof(SetGenerator<>), elementType);
+ }
case nameof(GenericCollectionType.Enumerable):
+ {
+ if (collectionType.Type == type)
{
- if (collectionType.Type == type)
- {
- // Not a full list type, we can't fake it if it's anything other than
- // the actual IEnumerable interface itelf.
- Type elementType = generics[0];
- return CreateGenericGenerator(typeof(EnumerableGenerator<>), elementType);
- }
-
- break;
+ // Not a full list type, we can't fake it if it's anything other than
+ // the actual IEnumerable interface itelf.
+ Type elementType = generics[0];
+ return CreateGenericGenerator(typeof(EnumerableGenerator<>), elementType);
}
+
+ break;
+ }
}
}
- // Resolve the generator from the type
- if (Generators.TryGetValue(type, out IAutoFakerGenerator? generator))
+ if (DataTableGenerator.TryCreateGenerator(context.CachedType, out DataTableGenerator dataTableGenerator))
{
- return generator;
+ return dataTableGenerator;
+ }
+
+ if (DataSetGenerator.TryCreateGenerator(context.CachedType, out DataSetGenerator dataSetGenerator))
+ {
+ return dataSetGenerator;
}
return CreateGenericGenerator(typeof(TypeGenerator<>), type);
@@ -174,6 +178,6 @@ private static IAutoFakerGenerator CreateDictionaryGenerator(Type[] generics)
private static IAutoFakerGenerator CreateGenericGenerator(Type generatorType, params Type[] genericTypes)
{
Type type = generatorType.MakeGenericType(genericTypes);
- return (IAutoFakerGenerator)Activator.CreateInstance(type);
+ return (IAutoFakerGenerator) Activator.CreateInstance(type);
}
}
\ No newline at end of file
diff --git a/src/Generators/Types/DataSetGenerator.cs b/src/Generators/Types/DataSetGenerator.cs
index 94aef48..048b731 100644
--- a/src/Generators/Types/DataSetGenerator.cs
+++ b/src/Generators/Types/DataSetGenerator.cs
@@ -9,10 +9,9 @@
namespace Soenneker.Utils.AutoBogus.Generators.Types;
-internal abstract class DataSetGenerator
- : IAutoFakerGenerator
+internal abstract class DataSetGenerator : IAutoFakerGenerator
{
- public static bool TryCreateGenerator(CachedType dataSetType, out DataSetGenerator generator)
+ public static bool TryCreateGenerator(CachedType dataSetType, out DataSetGenerator? generator)
{
generator = default;
diff --git a/src/Generators/Types/DateOnlyGenerator.cs b/src/Generators/Types/DateOnlyGenerator.cs
new file mode 100644
index 0000000..27ae733
--- /dev/null
+++ b/src/Generators/Types/DateOnlyGenerator.cs
@@ -0,0 +1,13 @@
+using Soenneker.Utils.AutoBogus.Context;
+using Soenneker.Utils.AutoBogus.Generators.Abstract;
+
+namespace Soenneker.Utils.AutoBogus.Generators.Types;
+
+internal sealed class DateOnlyGenerator
+ : IAutoFakerGenerator
+{
+ object IAutoFakerGenerator.Generate(AutoFakerContext context)
+ {
+ return context.Faker.Date.RecentDateOnly();
+ }
+}
\ No newline at end of file
diff --git a/src/Generators/Types/ListGenerator.cs b/src/Generators/Types/ListGenerator.cs
index 00496e6..1a7ce47 100644
--- a/src/Generators/Types/ListGenerator.cs
+++ b/src/Generators/Types/ListGenerator.cs
@@ -16,7 +16,7 @@ object IAutoFakerGenerator.Generate(AutoFakerContext context)
{
list = (List)Activator.CreateInstance(context.GenerateType);
}
- catch (Exception ex)
+ catch
{
list = [];
}
diff --git a/src/Generators/Types/ReadOnlyDictionaryGenerator.cs b/src/Generators/Types/ReadOnlyDictionaryGenerator.cs
index 6477c19..0a1ecbb 100644
--- a/src/Generators/Types/ReadOnlyDictionaryGenerator.cs
+++ b/src/Generators/Types/ReadOnlyDictionaryGenerator.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using Soenneker.Utils.AutoBogus.Context;
-using Soenneker.Utils.AutoBogus.Extensions;
using Soenneker.Utils.AutoBogus.Generators.Abstract;
namespace Soenneker.Utils.AutoBogus.Generators.Types;
diff --git a/src/Generators/Types/TimeOnlyGenerator.cs b/src/Generators/Types/TimeOnlyGenerator.cs
new file mode 100644
index 0000000..b76aa41
--- /dev/null
+++ b/src/Generators/Types/TimeOnlyGenerator.cs
@@ -0,0 +1,13 @@
+using Soenneker.Utils.AutoBogus.Context;
+using Soenneker.Utils.AutoBogus.Generators.Abstract;
+
+namespace Soenneker.Utils.AutoBogus.Generators.Types;
+
+internal sealed class TimeOnlyGenerator
+ : IAutoFakerGenerator
+{
+ object IAutoFakerGenerator.Generate(AutoFakerContext context)
+ {
+ return context.Faker.Date.RecentTimeOnly();
+ }
+}
\ No newline at end of file
diff --git a/src/Generators/Types/TypeGenerator.cs b/src/Generators/Types/TypeGenerator.cs
index f7f7bdd..4529bfb 100644
--- a/src/Generators/Types/TypeGenerator.cs
+++ b/src/Generators/Types/TypeGenerator.cs
@@ -1,4 +1,5 @@
-using Soenneker.Utils.AutoBogus.Context;
+using System;
+using Soenneker.Utils.AutoBogus.Context;
using Soenneker.Utils.AutoBogus.Generators.Abstract;
namespace Soenneker.Utils.AutoBogus.Generators.Types;
@@ -15,6 +16,29 @@ object IAutoFakerGenerator.Generate(AutoFakerContext context)
// Populate the generated instance
context.FakerBinder.PopulateInstance(instance, context);
+ return instance;
+ }
+}
+
+internal sealed class TypeGenerator: IAutoFakerGenerator
+{
+ readonly Type _type;
+
+ public TypeGenerator(Type type)
+ {
+ _type = type;
+ }
+
+ object IAutoFakerGenerator.Generate(AutoFakerContext context)
+ {
+ // Note that all instances are converted to object to cater for boxing and struct population
+ // When setting a value via reflection on a struct a copy is made
+ // This means the changes are applied to a different instance to the one created here
+ object? instance = context.FakerBinder.CreateInstance(context, _type);
+
+ // Populate the generated instance
+ context.FakerBinder.PopulateInstance(instance, context, _type);
+
return instance;
}
}
\ No newline at end of file
diff --git a/src/Soenneker - Backup.Utils.AutoBogus.csproj b/src/Soenneker - Backup.Utils.AutoBogus.csproj
deleted file mode 100644
index 181270f..0000000
--- a/src/Soenneker - Backup.Utils.AutoBogus.csproj
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
- netstandard2.1
- enable
- AnyCPU
- $(NoWarn);1591
-
-
-
- An updated version of AutoBogus, which is an auto creator/populator for Bogus
- 2.1.0
- $(BUILD_VERSION)
- Soenneker.Utils.AutoBogus
- Soenneker.Utils.AutoBogus
- utils autobogus autofaker faker bogus tests mock c# .net csharp dotnet
- Copyright © 2023 Jake Soenneker
- Jake Soenneker
- https://soenneker.com
- true
- true
- true
- snupkg
- true
- MIT
- https://github.com/soenneker/soenneker.utils.autobogus
- https://github.com/soenneker/soenneker.utils.autobogus
- false
- true
- latest
- README.md
- icon.png
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Soenneker.Utils.AutoBogus.csproj b/src/Soenneker.Utils.AutoBogus.csproj
index a24adc3..6d28079 100644
--- a/src/Soenneker.Utils.AutoBogus.csproj
+++ b/src/Soenneker.Utils.AutoBogus.csproj
@@ -1,7 +1,7 @@
- netstandard2.1
+ net6.0;net7.0;net8.0
enable
AnyCPU
$(NoWarn);1591
@@ -32,10 +32,6 @@
icon.png
-
-
-
-
@@ -46,7 +42,6 @@
-
diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs
index 15e790f..c7acdbc 100644
--- a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs
+++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs
@@ -10,7 +10,6 @@
using Soenneker.Utils.AutoBogus.Generators;
using Soenneker.Utils.AutoBogus.Tests.Dtos.Simple;
using Xunit;
-using Soenneker.Utils.AutoBogus.Extensions;
using Soenneker.Utils.AutoBogus.Generators.Abstract;
using Soenneker.Utils.AutoBogus.Generators.Types;
using Soenneker.Utils.AutoBogus.Tests.Extensions;
diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/BogusBenchmarks.cs b/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/BogusBenchmarks.cs
index 968f4fc..dff9683 100644
--- a/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/BogusBenchmarks.cs
+++ b/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/BogusBenchmarks.cs
@@ -13,7 +13,7 @@ public void Setup()
_faker = new Faker();
}
- [Benchmark(Baseline = true)]
+ [Benchmark]
public string Bogus_string()
{
return _faker.Vehicle.Vin();
@@ -24,4 +24,10 @@ public int Bogus_int()
{
return _faker.Random.Int();
}
+
+ [Benchmark]
+ public Faker Bogus_ctor()
+ {
+ return new Faker();
+ }
}
diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs b/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs
index 4fe0aa7..16e553c 100644
--- a/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs
+++ b/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs
@@ -7,29 +7,35 @@ namespace Soenneker.Utils.AutoBogus.Tests.Benchmarking.Benchmarks;
public class GenerateBenchmarks
{
- private IAutoFaker _faker = default!;
+ private IAutoFaker _autoFaker = default!;
[GlobalSetup]
public void Setup()
{
- _faker = AutoFaker.Create();
+ _autoFaker = AutoFaker.Create();
}
[Benchmark(Baseline = true)]
public Order Generate_complex()
{
- return _faker.Generate();
+ return _autoFaker.Generate();
}
[Benchmark]
public TestClassWithSingleProperty Generate_simple_reference()
{
- return _faker.Generate>();
+ return _autoFaker.Generate>();
}
[Benchmark]
- public int Generate_simple_value()
+ public int Generate_int()
{
- return _faker.Generate();
+ return _autoFaker.Generate();
+ }
+
+ [Benchmark]
+ public string Generate_string()
+ {
+ return _autoFaker.Generate();
}
}
\ No newline at end of file
diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Dtos/Complex/OrderItem.cs b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/Complex/OrderItem.cs
index be09023..cf1f0cb 100644
--- a/test/Soenneker.Utils.AutoBogus.Tests/Dtos/Complex/OrderItem.cs
+++ b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/Complex/OrderItem.cs
@@ -2,6 +2,8 @@
namespace Soenneker.Utils.AutoBogus.Tests.Dtos.Complex;
+using System;
+
public sealed class OrderItem
{
public OrderItem(Product product)
@@ -12,4 +14,6 @@ public OrderItem(Product product)
public Product Product { get; }
public Quantity Quantity { get; set; }
public IDictionary Discounts { get; set; }
+ public TimeOnly MostEffectiveAt { get; set; }
+ public DateOnly MostEffectiveOn { get; set; }
}
\ No newline at end of file
diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Dtos/GenerateAssertions.cs b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/GenerateAssertions.cs
index a8e61b9..2d915ac 100644
--- a/test/Soenneker.Utils.AutoBogus.Tests/Dtos/GenerateAssertions.cs
+++ b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/GenerateAssertions.cs
@@ -29,6 +29,8 @@ internal GenerateAssertions(object subject) : base(subject)
Assertions.Add(IsChar, AssertChar);
Assertions.Add(IsDateTime, AssertDateTime);
Assertions.Add(IsDateTimeOffset, AssertDateTimeOffset);
+ Assertions.Add(IsDateOnly, AssertDateOnly);
+ Assertions.Add(IsTimeOnly, AssertTimeOnly);
Assertions.Add(IsDecimal, AssertDecimal);
Assertions.Add(IsDouble, AssertDouble);
Assertions.Add(IsFloat, AssertFloat);
@@ -165,6 +167,8 @@ private void AssertDefaultValue(MemberInfo memberInfo)
private static bool IsChar(Type type) => type == typeof(char);
private static bool IsDateTime(Type type) => type == typeof(DateTime);
private static bool IsDateTimeOffset(Type type) => type == typeof(DateTimeOffset);
+ private static bool IsDateOnly(Type type) => type == typeof(DateOnly);
+ private static bool IsTimeOnly(Type type) => type == typeof(TimeOnly);
private static bool IsDecimal(Type type) => type == typeof(decimal);
private static bool IsDouble(Type type) => type == typeof(double);
private static bool IsFloat(Type type) => type == typeof(float);
@@ -194,6 +198,8 @@ private void AssertDefaultValue(MemberInfo memberInfo)
private static string AssertChar(string path, Type type, object value) => value != null && char.TryParse(value.ToString(), out char result) && result != default(char) ? null : GetAssertionMessage(path, type, value);
private static string AssertDateTime(string path, Type type, object value) => value != null && DateTime.TryParse(value.ToString(), out DateTime result) && result != default ? null : GetAssertionMessage(path, type, value);
private static string AssertDateTimeOffset(string path, Type type, object value) => value != null && DateTimeOffset.TryParse(value.ToString(), out DateTimeOffset result) && result != default ? null : GetAssertionMessage(path, type, value);
+ private static string AssertDateOnly(string path, Type type, object value) => value != null && DateOnly.TryParse(value.ToString(), out DateOnly result) && result != default ? null : GetAssertionMessage(path, type, value);
+ private static string AssertTimeOnly(string path, Type type, object value) => value != null && TimeOnly.TryParse(value.ToString(), out TimeOnly result) && result != default ? null : GetAssertionMessage(path, type, value);
private static string AssertDecimal(string path, Type type, object value) => value != null && decimal.TryParse(value.ToString(), out decimal result) && result != default ? null : GetAssertionMessage(path, type, value);
private static string AssertDouble(string path, Type type, object value) => value != null && double.TryParse(value.ToString(), out double result) && result != default ? null : GetAssertionMessage(path, type, value);
private static string AssertFloat(string path, Type type, object value) => value != null && float.TryParse(value.ToString(), out float result) && result != default ? null : GetAssertionMessage(path, type, value);
diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TypeExtensions.cs b/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TestTypeExtensions.cs
similarity index 94%
rename from test/Soenneker.Utils.AutoBogus.Tests/Extensions/TypeExtensions.cs
rename to test/Soenneker.Utils.AutoBogus.Tests/Extensions/TestTypeExtensions.cs
index a798567..4ab1359 100644
--- a/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TypeExtensions.cs
+++ b/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TestTypeExtensions.cs
@@ -3,7 +3,7 @@
namespace Soenneker.Utils.AutoBogus.Tests.Extensions;
-public static class TypeExtensions
+public static class TestTypeExtensions
{
internal static bool IsEnum(this Type type)
{
diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Soenneker.Utils.AutoBogus.Tests.csproj b/test/Soenneker.Utils.AutoBogus.Tests/Soenneker.Utils.AutoBogus.Tests.csproj
index e6f59a0..036d8e2 100644
--- a/test/Soenneker.Utils.AutoBogus.Tests/Soenneker.Utils.AutoBogus.Tests.csproj
+++ b/test/Soenneker.Utils.AutoBogus.Tests/Soenneker.Utils.AutoBogus.Tests.csproj
@@ -20,8 +20,8 @@
-
-
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive