diff --git a/README.md b/README.md index 9623e7c..172ffc7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It's a replacement for the abandoned [AutoBogus](https://github.com/nickdodd79/A The goals are to be *fast*, and support the latest types in .NET. -.NET Standard 2.1 is required. +.NET 6+ is supported. ## Installation @@ -19,8 +19,8 @@ The goals are to be *fast*, and support the latest types in .NET. dotnet add package Soenneker.Utils.AutoBogus ``` -A Bogus `Faker` takes a long time to initialize, so AutoFaker will mirror Faker in this sense. Thus, `AutoFaker` was dropped from this package. +⚠️ A Bogus `Faker` takes a long time to initialize, so AutoFaker will mirror Faker in this sense. Thus, `AutoFaker` was dropped from this package. -⚠️ It is recommended that a single instance of `AutoFaker` be used if possible. The static usage of `AutoFaker.Generate<>()` should be avoided (as it constructors a new `Faker`), but is available. +It's recommended that a single instance of `AutoFaker` be used if possible. The static usage of `AutoFaker.Generate<>()` should be avoided (as it creates a new `Faker`), but is available. This is a work in progress. Contribution is welcomed. \ No newline at end of file diff --git a/src/Abstract/IAutoFaker.cs b/src/Abstract/IAutoFaker.cs index 31554ee..44d5e36 100644 --- a/src/Abstract/IAutoFaker.cs +++ b/src/Abstract/IAutoFaker.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Bogus; +using Soenneker.Utils.AutoBogus.Config; using Soenneker.Utils.AutoBogus.Config.Abstract; namespace Soenneker.Utils.AutoBogus.Abstract; @@ -9,13 +11,17 @@ namespace Soenneker.Utils.AutoBogus.Abstract; /// public interface IAutoFaker { + void SetConfig(AutoFakerConfig config); + + void SetFaker(Faker faker); + /// /// Generates an instance of type . /// /// The type of instance to generate. /// A handler to build the generate request configuration. /// The generated instance. - TType Generate(Action configure = null); + TType Generate(Action? configure = null); /// /// Generates a collection of instances of type . @@ -24,5 +30,5 @@ public interface IAutoFaker /// The number of instances to generate. /// A handler to build the generate request configuration. /// The generated collection of instances. - List Generate(int count, Action configure = null); + List Generate(int count, Action? configure = null); } \ No newline at end of file diff --git a/src/Abstract/IAutoFakerBinder.cs b/src/Abstract/IAutoFakerBinder.cs index aa03de6..77de958 100644 --- a/src/Abstract/IAutoFakerBinder.cs +++ b/src/Abstract/IAutoFakerBinder.cs @@ -1,6 +1,3 @@ -using System; -using System.Reflection; -using Bogus; using Soenneker.Utils.AutoBogus.Context; namespace Soenneker.Utils.AutoBogus.Abstract; @@ -8,7 +5,7 @@ namespace Soenneker.Utils.AutoBogus.Abstract; /// /// An interface for binding generated instances. /// -public interface IAutoFakerBinder : IBinder +public interface IAutoFakerBinder { /// /// Creates an instance of . @@ -18,20 +15,15 @@ public interface IAutoFakerBinder : IBinder /// The created instance. TType? CreateInstance(AutoFakerContext context); - object? CreateInstance(AutoFakerContext context, Type type); - /// /// Populates the provided instance with generated values. /// /// The type of instance to populate. /// The instance to populate. /// The instance for the generate request. - /// An optional collection of members to populate. If null, all writable instance members are populated. /// /// Due to the boxing nature of value types, the parameter is an object. This means the populated /// 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); + void PopulateInstance(object instance, AutoFakerContext context); } \ No newline at end of file diff --git a/src/AutoFaker.cs b/src/AutoFaker.cs index d0a462f..e77a5a0 100644 --- a/src/AutoFaker.cs +++ b/src/AutoFaker.cs @@ -1,31 +1,56 @@ using System; using System.Collections.Generic; +using Bogus; using Soenneker.Utils.AutoBogus.Abstract; using Soenneker.Utils.AutoBogus.Config; using Soenneker.Utils.AutoBogus.Config.Abstract; using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Extensions; -using Soenneker.Utils.AutoBogus.Services; namespace Soenneker.Utils.AutoBogus; /// public sealed class AutoFaker : IAutoFaker { - private AutoFaker(AutoFakerConfig fakerConfig) + public AutoFakerConfig Config { get; private set; } + + internal AutoFakerBinder Binder { get; set; } + + public Faker Faker { get; set; } + + public AutoFaker(Action? configure = null) + { + Faker = new Faker(); + + Config = new AutoFakerConfig(); + + if (configure != null) + { + var builder = new AutoFakerConfigBuilder(Config, this); + + configure.Invoke(builder); + } + + Binder = new AutoFakerBinder(Config); + } + + public void SetConfig(AutoFakerConfig config) { - FakerConfig = fakerConfig; + Config = config; } - internal AutoFakerConfig FakerConfig { get; } + public void SetFaker(Faker faker) + { + Faker = faker; + } - TType IAutoFaker.Generate(Action configure) + TType IAutoFaker.Generate(Action? configure) { AutoFakerContext context = CreateContext(configure); return context.Generate(); } - List IAutoFaker.Generate(int count, Action configure) + List IAutoFaker.Generate(int count, Action? configure) { AutoFakerContext context = CreateContext(configure); return context.GenerateMany(count); @@ -35,43 +60,25 @@ List IAutoFaker.Generate(int count, Action /// A handler to build the default faker configuration. - public static void Configure(Action? configure) + public void Configure(Action? configure) { if (configure == null) return; - var builder = new AutoFakerConfigBuilder(DefaultConfigService.Config); + var builder = new AutoFakerConfigBuilder(Config, this); configure.Invoke(builder); } - /// - /// Creates a configured instance. - /// - /// A handler to build the faker configuration. - /// The configured instance. - public static AutoFaker Create(Action? configure = null) - { - var config = new AutoFakerConfig(DefaultConfigService.Config); - - if (configure == null) - return new AutoFaker(config); - - var builder = new AutoFakerConfigBuilder(config); - - configure.Invoke(builder); - - return new AutoFaker(config); - } - /// /// Generates an instance of type . /// /// The type of instance to generate. /// A handler to build the generate request configuration. /// The generated instance. + [Obsolete("This creates a new Bogus.Faker on each call (expensive); use one AutoFaker across your context")] public static TType Generate(Action? configure = null) { - IAutoFaker faker = Create(configure); + IAutoFaker faker = new AutoFaker(configure); return faker.Generate(); } @@ -82,22 +89,21 @@ public static TType Generate(Action? configur /// The number of instances to generate. /// A handler to build the generate request configuration. /// The generated collection of instances. + [Obsolete("This creates a new Bogus.Faker on each call (expensive); use one AutoFaker across your context")] public static List Generate(int count, Action? configure = null) { - IAutoFaker faker = Create(configure); + IAutoFaker faker = new AutoFaker(configure); return faker.Generate(count); } private AutoFakerContext CreateContext(Action? configure) { - var config = new AutoFakerConfig(FakerConfig); - - if (configure == null) - return new AutoFakerContext(config); + if (configure == null) + return new AutoFakerContext(Config, Faker, Binder); - var builder = new AutoFakerConfigBuilder(config); + var builder = new AutoFakerConfigBuilder(Config, this); configure.Invoke(builder); - return new AutoFakerContext(config); + return new AutoFakerContext(Config, Faker, Binder); } } \ No newline at end of file diff --git a/src/AutoFakerBinder.cs b/src/AutoFakerBinder.cs index 5aa653b..ba13958 100644 --- a/src/AutoFakerBinder.cs +++ b/src/AutoFakerBinder.cs @@ -1,88 +1,60 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Data; using System.Linq; using System.Reflection; using Soenneker.Reflection.Cache.Constructors; +using Soenneker.Reflection.Cache.Extensions; +using Soenneker.Reflection.Cache.Methods; +using Soenneker.Reflection.Cache.Parameters; using Soenneker.Reflection.Cache.Types; using Soenneker.Utils.AutoBogus.Abstract; +using Soenneker.Utils.AutoBogus.Config; using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Extensions; using Soenneker.Utils.AutoBogus.Generators; using Soenneker.Utils.AutoBogus.Generators.Abstract; using Soenneker.Utils.AutoBogus.Services; -using Binder = Bogus.Binder; namespace Soenneker.Utils.AutoBogus; /// /// A class for binding generated instances. /// -public class AutoFakerBinder : Binder, IAutoFakerBinder +public class AutoFakerBinder : IAutoFakerBinder { + private readonly AutoFakerConfig _autoFakerConfig; + + private readonly CachedType _genericDictionary = CacheService.Cache.GetCachedType(typeof(IDictionary<,>)); + private readonly CachedType _enumerable = CacheService.Cache.GetCachedType(typeof(IEnumerable<>)); + + private readonly Dictionary> _autoMembersCache = []; + + public AutoFakerBinder(AutoFakerConfig autoFakerConfig) + { + _autoFakerConfig = autoFakerConfig; + } + /// /// Creates an instance of . /// /// The type of instance to create. /// The instance for the generate request. /// The created instance of . - public virtual TType? CreateInstance(AutoFakerContext? context) + public TType? CreateInstance(AutoFakerContext? context) { if (context == null) return default; Type type = typeof(TType); - - 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); - - } - - 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); - } + CachedParameter[] parametersInfo = constructor.GetCachedParameters(); - 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++) @@ -90,8 +62,7 @@ public class AutoFakerBinder : Binder, IAutoFakerBinder parameters[i] = GetParameterGenerator(type, parametersInfo[i], context).Generate(context); } - return (TType?)constructor.Invoke(parameters); - + return (TType?) constructor.Invoke(parameters); } /// @@ -100,172 +71,122 @@ public class AutoFakerBinder : Binder, IAutoFakerBinder /// The type of instance to populate. /// The instance to populate. /// The instance for the generate request. - /// An optional collection of members to populate. If null, all writable instance members are populated. /// /// Due to the boxing nature of value types, the parameter is an object. This means the populated /// values are applied to the provided instance and not a copy. /// - public virtual void PopulateInstance(object? instance, AutoFakerContext? context, MemberInfo[]? members = null) + public void PopulateInstance(object instance, AutoFakerContext context) { - // We can only populate non-null instances - if (instance == null || context == null) - { - return; - } - Type type = typeof(TType); CachedType cachedType = CacheService.Cache.GetCachedType(type); // Iterate the members and bind a generated value - List autoMembers = GetMembersToPopulate(cachedType, members); + List autoMembers = GetMembersToPopulate(cachedType); - foreach (AutoMember? member in autoMembers) + for (var i = 0; i < autoMembers.Count; i++) { - if (member.Type != null) + AutoMember member = autoMembers[i]; + // 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.CachedType, $"{type.FullName}.{member.Name}", context)) { - // 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(); + continue; } - } - } - - 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); + context.Setup(type, member.CachedType, member.Name); - // Iterate the members and bind a generated value - List autoMembers = GetMembersToPopulate(cachedType, members); + context.TypesStack.Push(member.CachedType.CacheKey.Value); - 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; - } + // Generate a random value and bind it to the instance + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.GetGenerator(context); - 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); + object? value = generator.Generate(context); + if (value != null) + { try { if (!member.IsReadOnly) { member.Setter.Invoke(instance, value); } - else if (member.CachedType.IsDictionary()) + else if (member.CachedType.IsDictionary) { PopulateDictionary(value, instance, member); } - else if (member.CachedType.IsCollection()) + else if (member.CachedType.IsCollection) { PopulateCollection(value, instance, member); } } - catch + catch (Exception e) { + Console.WriteLine(e.ToString()); } - - // Remove the current type from the type stack so siblings can be created - context.TypesStack.Pop(); } + + // 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) + private bool ShouldSkip(CachedType cachedType, string path, AutoFakerContext context) { // Skip if the type is found - if (context.AutoFakerConfig.SkipTypes.Contains(type)) + if (_autoFakerConfig.SkipTypes != null && _autoFakerConfig.SkipTypes.Contains(cachedType.Type)) { return true; } // Skip if the path is found - if (context.AutoFakerConfig.SkipPaths.Contains(path)) + if (_autoFakerConfig.SkipPaths != null && _autoFakerConfig.SkipPaths.Contains(path)) { return true; } //check if tree depth is reached - int? treeDepth = context.AutoFakerConfig.TreeDepth.Invoke(context); + int? treeDepth = _autoFakerConfig.TreeDepth; - if (treeDepth.HasValue && context.TypesStack.Count >= treeDepth) - return true; + if (treeDepth != null) + { + if (context.TypesStack.Count >= treeDepth) + return true; + } + + if (context.TypesStack.Count == 0) + return false; // Finally check if the recursive depth has been reached - int count = context.TypesStack.Count(t => t == type); - int recursiveDepth = context.AutoFakerConfig.RecursiveDepth.Invoke(context); + int count = context.TypesStack.Count(c => c == cachedType.CacheKey); + int recursiveDepth = _autoFakerConfig.RecursiveDepth; + + if (count >= recursiveDepth) + return true; - return count >= recursiveDepth; + return false; } - private static CachedConstructor? GetConstructor(CachedType type) + private CachedConstructor? GetConstructor(CachedType type) { CachedConstructor[]? constructors = type.GetCachedConstructors(); - if (type.IsDictionary()) + if (type.IsDictionary) { - return ResolveTypedConstructor(typeof(IDictionary<,>), constructors); + return ResolveTypedConstructor(_genericDictionary, constructors); } - if (type.IsEnumerable()) + if (type.IsEnumerable) { - return ResolveTypedConstructor(typeof(IEnumerable<>), constructors); + return ResolveTypedConstructor(_enumerable, constructors); } - foreach (CachedConstructor constructor in constructors) + for (var i = 0; i < constructors.Length; i++) { - if (constructor.GetParameters().Length == 0) + CachedConstructor constructor = constructors[i]; + + if (constructor.GetCachedParameters().Length == 0) { return constructor; } @@ -274,24 +195,24 @@ private static bool ShouldSkip(Type type, string path, AutoFakerContext context) return constructors.Length > 0 ? constructors[0] : null; } - private static CachedConstructor? ResolveTypedConstructor(Type type, CachedConstructor[] constructors) + private static CachedConstructor? ResolveTypedConstructor(CachedType type, CachedConstructor[] constructors) { for (int i = 0; i < constructors.Length; i++) { CachedConstructor c = constructors[i]; - ParameterInfo[] parameters = c.GetParameters(); + CachedParameter[] parameters = c.GetCachedParameters(); if (parameters.Length != 1) continue; - ParameterInfo parameter = parameters[0]; - Type parameterType = parameter.ParameterType; + CachedParameter parameter = parameters[0]; + CachedType parameterType = parameter.CachedParameterType; if (!parameterType.IsGenericType) continue; - Type genericTypeDefinition = parameterType.GetGenericTypeDefinition(); + CachedType? genericTypeDefinition = parameterType.GetCachedGenericTypeDefinition(); if (genericTypeDefinition == type) { @@ -302,80 +223,51 @@ private static bool ShouldSkip(Type type, string path, AutoFakerContext context) return null; } - private static IAutoFakerGenerator GetParameterGenerator(Type type, ParameterInfo parameter, AutoFakerContext context) + private static IAutoFakerGenerator GetParameterGenerator(Type type, CachedParameter parameter, AutoFakerContext context) { - context.Setup(type, parameter.ParameterType, parameter.Name); + context.Setup(type, parameter.CachedParameterType, parameter.Name); - return GeneratorFactory.GetGenerator(context); + return AutoFakerGeneratorFactory.GetGenerator(context); } - private List GetMembersToPopulate(CachedType type, MemberInfo[]? members) + private List GetMembersToPopulate(CachedType cachedType) { - // If a list of members is provided, no others should be populated - if (members != null) - { - var autoMembersList = new List(members.Length); + if (_autoMembersCache.TryGetValue(cachedType, out List? members)) + return members; - for (int i = 0; i < members.Length; i++) - { - autoMembersList.Add(new AutoMember(members[i])); - } + var autoMembers = new List(); - return autoMembersList; - } + PropertyInfo[] properties = cachedType.GetProperties()!; - // Get the baseline members resolved by Bogus - var autoMembers = new List(); + FieldInfo[]? fields = cachedType.GetFields(); - foreach (MemberInfo? member in GetMembers(type.Type).Values) + for (var i = 0; i < properties.Length; i++) { - autoMembers.Add(new AutoMember(member)); + PropertyInfo property = properties[i]; + autoMembers.Add(new AutoMember(property)); } - MemberInfo[] memberInfos = type.GetMembers()!; - int length = memberInfos.Length; - - for (int i = 0; i < length; i++) + for (var i = 0; i < fields.Length; i++) { - MemberInfo member = memberInfos[i]; - - // Then check if any other members can be populated - var autoMember = new AutoMember(member); - - bool found = false; - for (int j = 0; j < autoMembers.Count; j++) - { - if (autoMembers[j].Name == autoMember.Name) - { - found = true; - break; - } - } - - if (!found) - { - // A readonly dictionary or collection member can use the Add() method - if (autoMember.IsReadOnly && autoMember.CachedType.IsDictionary()) - { - autoMembers.Add(autoMember); - } - else if (autoMember.IsReadOnly && autoMember.CachedType.IsCollection()) - { - autoMembers.Add(autoMember); - } - } + FieldInfo field = fields[i]; + autoMembers.Add(new AutoMember(field)); } + _autoMembersCache.TryAdd(cachedType, autoMembers); + return autoMembers; } private static void PopulateDictionary(object value, object parent, AutoMember member) { + if (value is not IDictionary dictionary) + return; + object? instance = member.Getter(parent); - Type[] argTypes = member.CachedType.GetAddMethodArgumentTypes(); - MethodInfo? addMethod = GetAddMethod(member.Type, argTypes); + CachedType[] argTypes = member.CachedType.GetAddMethodArgumentTypes(); + CachedMethod? addMethod = GetAddMethod(member.CachedType, argTypes); - if (instance != null && addMethod != null && value is IDictionary dictionary) + if (instance != null && addMethod != null) { foreach (object? key in dictionary.Keys) { @@ -386,11 +278,14 @@ private static void PopulateDictionary(object value, object parent, AutoMember m private static void PopulateCollection(object value, object parent, AutoMember member) { + if (value is not ICollection collection) + return; + object? instance = member.Getter(parent); - Type[] argTypes = member.CachedType.GetAddMethodArgumentTypes(); - MethodInfo? addMethod = GetAddMethod(member.Type, argTypes); + CachedType[] argTypes = member.CachedType.GetAddMethodArgumentTypes(); + CachedMethod? addMethod = GetAddMethod(member.CachedType, argTypes); - if (instance != null && addMethod != null && value is ICollection collection) + if (instance != null && addMethod != null) { foreach (object? item in collection) { @@ -399,18 +294,18 @@ private static void PopulateCollection(object value, object parent, AutoMember m } } - private static MethodInfo? GetAddMethod(Type type, Type[] argTypes) + private static CachedMethod? GetAddMethod(CachedType cachedType, CachedType[] argTypes) { - MethodInfo? method = type.GetMethod("Add", argTypes); + var method = cachedType.GetCachedMethod("Add", argTypes.ToTypes()); if (method != null) return method; - Type[] interfaces = CacheService.Cache.GetCachedType(type).GetInterfaces()!; + var interfaces = cachedType.GetCachedInterfaces(); for (int i = 0; i < interfaces.Length; i++) { - MethodInfo? interfaceMethod = GetAddMethod(interfaces[i], argTypes); + CachedMethod? interfaceMethod = GetAddMethod(interfaces[i], argTypes); if (interfaceMethod != null) { diff --git a/src/AutoMember.cs b/src/AutoMember.cs index 9e7d64c..bc6850e 100644 --- a/src/AutoMember.cs +++ b/src/AutoMember.cs @@ -1,49 +1,74 @@ using System; using System.Reflection; using Soenneker.Reflection.Cache.Types; -using Soenneker.Utils.AutoBogus.Extensions; using Soenneker.Utils.AutoBogus.Services; namespace Soenneker.Utils.AutoBogus; internal sealed class AutoMember { - internal string Name { get; } + internal readonly string Name; - internal Type Type { get; } + //internal Type Type { get; } - internal CachedType CachedType { get; } + internal readonly CachedType CachedType; - internal bool IsReadOnly { get; } + internal readonly bool IsReadOnly; - internal Func Getter { get; } + internal readonly Func Getter; - internal Action Setter { get; } + internal readonly Action Setter; - internal AutoMember(MemberInfo memberInfo) + //internal AutoMember(CachedMember cachedMember) + //{ + // Name = cachedMember.Name; + + // // Extract the required member info + // if (cachedMember.IsField) + // { + // var fieldInfo = cachedMember.MemberInfo as FieldInfo; + + // Type = fieldInfo.FieldType; + // CachedType = CacheService.Cache.GetCachedType(Type); + // IsReadOnly = !fieldInfo.IsPrivate && fieldInfo.IsInitOnly; + // Getter = fieldInfo.GetValue; + // Setter = fieldInfo.SetValue; + // } + // else if (cachedMember.IsProperty) + // { + // var propertyInfo = cachedMember.MemberInfo as PropertyInfo; + + // Type = propertyInfo.PropertyType; + // CachedType = CacheService.Cache.GetCachedType(Type); + // IsReadOnly = !propertyInfo.CanWrite; + // Getter = obj => propertyInfo.GetValue(obj, new object[0]); + // Setter = (obj, value) => propertyInfo.SetValue(obj, value, new object[0]); + // } + //} + + internal AutoMember(FieldInfo fieldInfo) { - Name = memberInfo.Name; + Name = fieldInfo.Name; // Extract the required member info - if (memberInfo.IsField()) - { - var fieldInfo = memberInfo as FieldInfo; - - Type = fieldInfo.FieldType; - CachedType = CacheService.Cache.GetCachedType(Type); - IsReadOnly = !fieldInfo.IsPrivate && fieldInfo.IsInitOnly; - Getter = fieldInfo.GetValue; + + CachedType = CacheService.Cache.GetCachedType(fieldInfo.FieldType); + IsReadOnly = !fieldInfo.IsPrivate && fieldInfo.IsInitOnly; + Getter = fieldInfo.GetValue; + + if (!IsReadOnly) Setter = fieldInfo.SetValue; - } - else if (memberInfo.IsProperty()) - { - var propertyInfo = memberInfo as PropertyInfo; - - Type = propertyInfo.PropertyType; - CachedType = CacheService.Cache.GetCachedType(Type); - IsReadOnly = !propertyInfo.CanWrite; - Getter = obj => propertyInfo.GetValue(obj, new object[0]); - Setter = (obj, value) => propertyInfo.SetValue(obj, value, new object[0]); - } + } + + internal AutoMember(PropertyInfo propertyInfo) + { + Name = propertyInfo.Name; + + CachedType = CacheService.Cache.GetCachedType(propertyInfo.PropertyType); + IsReadOnly = !propertyInfo.CanWrite; + Getter = obj => propertyInfo.GetValue(obj, []); + + if (!IsReadOnly) + Setter = (obj, value) => propertyInfo.SetValue(obj, value, []); } } \ No newline at end of file diff --git a/src/Config/AutoFakerConfig.cs b/src/Config/AutoFakerConfig.cs index 05f34e6..521b3de 100644 --- a/src/Config/AutoFakerConfig.cs +++ b/src/Config/AutoFakerConfig.cs @@ -1,75 +1,32 @@ using System; using System.Collections.Generic; -using Bogus; -using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Generators; namespace Soenneker.Utils.AutoBogus.Config; -internal sealed class AutoFakerConfig +public sealed class AutoFakerConfig { - internal const string DefaultLocale = "en"; - internal const int GenerateAttemptsThreshold = 3; + internal string Locale; - internal static readonly Func DefaultRepeatCount = _ => 3; - internal static readonly Func DefaultDataTableRowCount = _ => 15; - internal static readonly Func DefaultRecursiveDepth = _ => 2; - internal static readonly Func DefaultTreeDepth = _ => null; - internal static readonly Func DefaultDateTimeKind = _ => System.DateTimeKind.Local; + internal int RepeatCount; - internal string Locale { get; set; } - internal Func DateTimeKind { get; set; } - internal Func RepeatCount { get; set; } - internal Func DataTableRowCount { get; set; } - internal Func RecursiveDepth { get; set; } + internal int DataTableRowCount; + internal int RecursiveDepth; - internal AutoFakerBinder FakerBinder { get; set; } + internal HashSet? SkipTypes; - internal List SkipTypes { get; set; } + internal HashSet? SkipPaths; - internal List SkipPaths { get; set; } + internal List? Overrides; - internal List? Overrides { get; set; } - - public Func TreeDepth { get; set; } - - public Faker? Faker { get; set; } + public int? TreeDepth; internal AutoFakerConfig() { - Locale = DefaultLocale; - RepeatCount = DefaultRepeatCount; - DataTableRowCount = DefaultDataTableRowCount; - RecursiveDepth = DefaultRecursiveDepth; - TreeDepth = DefaultTreeDepth; - DateTimeKind = DefaultDateTimeKind; - FakerBinder = new AutoFakerBinder(); - SkipTypes = []; - SkipPaths = []; - Overrides = []; - - if (Faker != null) - return; - - Faker = new Faker(Locale); - } - - internal AutoFakerConfig(AutoFakerConfig fakerConfig) - { - Locale = fakerConfig.Locale; - RepeatCount = fakerConfig.RepeatCount; - DataTableRowCount = fakerConfig.DataTableRowCount; - RecursiveDepth = fakerConfig.RecursiveDepth; - TreeDepth = fakerConfig.TreeDepth; - DateTimeKind = fakerConfig.DateTimeKind; - FakerBinder = fakerConfig.FakerBinder; - SkipTypes = fakerConfig.SkipTypes; - SkipPaths = fakerConfig.SkipPaths; - Overrides = fakerConfig.Overrides; - - if (Faker != null) - return; - - Faker = fakerConfig.Faker ?? new Faker(Locale); + Locale = AutoFakerDefaultConfigOptions.DefaultLocale; + RepeatCount = AutoFakerDefaultConfigOptions.DefaultRepeatCount; + DataTableRowCount = AutoFakerDefaultConfigOptions.DefaultDataTableRowCount; + RecursiveDepth = AutoFakerDefaultConfigOptions.DefaultRecursiveDepth; + TreeDepth = AutoFakerDefaultConfigOptions.DefaultTreeDepth; } } \ No newline at end of file diff --git a/src/Config/AutoFakerConfigBuilder.cs b/src/Config/AutoFakerConfigBuilder.cs index 818bcb9..af7ed16 100644 --- a/src/Config/AutoFakerConfigBuilder.cs +++ b/src/Config/AutoFakerConfigBuilder.cs @@ -3,157 +3,133 @@ using Bogus; using Soenneker.Utils.AutoBogus.Config.Abstract; using Soenneker.Utils.AutoBogus.Config.Base; -using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Generators; namespace Soenneker.Utils.AutoBogus.Config; internal sealed class AutoFakerConfigBuilder : IAutoFakerDefaultConfigBuilder, IAutoGenerateConfigBuilder, IAutoFakerConfigBuilder { - internal AutoFakerConfigBuilder(AutoFakerConfig fakerConfig) + internal readonly AutoFakerConfig _autoFakerConfig; + + private readonly AutoFaker _autoFaker; + + internal AutoFakerConfigBuilder(AutoFakerConfig autoFakerConfig, AutoFaker autoFaker) { - FakerConfig = fakerConfig; + _autoFakerConfig = autoFakerConfig; + _autoFaker = autoFaker; } - internal AutoFakerConfig FakerConfig { get; } - - internal object[] Args { get; private set; } + internal object[]? Args { get; private set; } IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithLocale(string locale) => WithLocale(locale, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(int count) => WithRepeatCount(count, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(int count) => WithDataTableRowCount(count, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithDateTimeKind(Func dateTimeKind) => WithDateTimeKind(dateTimeKind, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithDateTimeKind(DateTimeKind dateTimeKind) => WithDateTimeKind(_ => dateTimeKind, this); - - - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(int count) => WithRepeatCount(context => count, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(int depth) => WithRecursiveDepth(depth, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(int? depth) => WithTreeDepth(depth, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(Func count) => - WithRepeatCount(count, this); - - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(int count) => WithDataTableRowCount(context => count, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithBinder(AutoFakerBinder fakerBinder) => WithBinder(fakerBinder, this); + //IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithFaker(Faker faker) => WithFaker(faker, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type) => WithSkip(type, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(Func count) => - WithDataTableRowCount(count, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type, string memberName) => + WithSkip(type, memberName, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(int depth) => WithRecursiveDepth(context => depth, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(string memberName) => WithSkip(memberName, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(Func depth) => - WithRecursiveDepth(depth, this); + IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithOverride(AutoFakerGeneratorOverride autoFakerGeneratorOverride) => + WithOverride(autoFakerGeneratorOverride, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(int? depth) => WithTreeDepth(context => depth, this); + IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithLocale(string locale) => WithLocale(locale, this); + IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(int count) => WithRepeatCount(count, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(Func depth) => - WithTreeDepth(depth, this); + IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(int count) => WithDataTableRowCount(count, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithBinder(AutoFakerBinder fakerBinder) => WithBinder(fakerBinder, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithFaker(Faker faker) => WithFaker(faker, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type) => WithSkip(type, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type, string memberName) => WithSkip(type, memberName, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(string memberName) => WithSkip(memberName, this); + IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(int depth) => WithRecursiveDepth(depth, this); - IAutoFakerDefaultConfigBuilder IBaseAutoFakerConfigBuilder.WithOverride(GeneratorOverride generatorOverride) => - WithOverride(generatorOverride, this); + IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(int? depth) => WithTreeDepth(depth, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithLocale(string locale) => WithLocale(locale, this); - - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithDateTimeKind(Func dateTimeKind) => WithDateTimeKind(dateTimeKind, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithDateTimeKind(DateTimeKind dateTimeKind) => WithDateTimeKind(_ => dateTimeKind, this); - - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(int count) => WithRepeatCount(context => count, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(Func count) => WithRepeatCount(count, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(int count) => WithDataTableRowCount(context => count, this); - - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(Func count) => - WithDataTableRowCount(count, this); - - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(int depth) => WithRecursiveDepth(context => depth, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(Func depth) => WithRecursiveDepth(depth, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(int? depth) => WithTreeDepth(context => depth, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(Func depth) => WithTreeDepth(depth, this); IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithBinder(AutoFakerBinder fakerBinder) => WithBinder(fakerBinder, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithFaker(Faker faker) => WithFaker(faker, this); + //IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithFaker(Faker faker) => WithFaker(faker, this); IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type) => WithSkip(type, this); IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type, string memberName) => WithSkip(type, memberName, this); IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(string memberName) => WithSkip(memberName, this); - IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithOverride(GeneratorOverride generatorOverride) => - WithOverride(generatorOverride, this); + IAutoGenerateConfigBuilder IBaseAutoFakerConfigBuilder.WithOverride(AutoFakerGeneratorOverride autoFakerGeneratorOverride) => + WithOverride(autoFakerGeneratorOverride, this); IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithLocale(string locale) => WithLocale(locale, this); - - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithDateTimeKind(Func dateTimeKind) => WithDateTimeKind(dateTimeKind, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithDateTimeKind(DateTimeKind dateTimeKind) => WithDateTimeKind(_ => dateTimeKind, this); - - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(int count) => WithRepeatCount(context => count, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(Func count) => WithRepeatCount(count, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(int count) => WithDataTableRowCount(context => count, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(Func count) => WithDataTableRowCount(count, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(int depth) => WithRecursiveDepth(context => depth, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(Func depth) => WithRecursiveDepth(depth, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(int? depth) => WithTreeDepth(context => depth, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(Func depth) => WithTreeDepth(depth, this); + IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithRepeatCount(int count) => WithRepeatCount(count, this); + + IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithDataTableRowCount(int count) => WithDataTableRowCount(count, this); + + IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithRecursiveDepth(int depth) => WithRecursiveDepth(depth, this); + + IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithTreeDepth(int? depth) => WithTreeDepth(depth, this); + IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithBinder(AutoFakerBinder fakerBinder) => WithBinder(fakerBinder, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithFaker(Faker faker) => WithFaker(faker, this); IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type) => WithSkip(type, this); IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(Type type, string memberName) => WithSkip(type, memberName, this); IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithSkip(string memberName) => WithSkip(memberName, this); - IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithOverride(GeneratorOverride generatorOverride) => WithOverride(generatorOverride, this); + + IAutoFakerConfigBuilder IBaseAutoFakerConfigBuilder.WithOverride(AutoFakerGeneratorOverride autoFakerGeneratorOverride) => + WithOverride(autoFakerGeneratorOverride, this); + IAutoFakerConfigBuilder IAutoFakerConfigBuilder.WithArgs(params object[] args) => WithArgs(args, this); - internal TBuilder WithLocale(string? locale, TBuilder builder) - { - FakerConfig.Locale = locale ?? AutoFakerConfig.DefaultLocale; - return builder; - } - - internal TBuilder WithDateTimeKind(Func kind, TBuilder builder) + internal TBuilder WithLocale(string locale, TBuilder builder) { - FakerConfig.DateTimeKind = kind ?? AutoFakerConfig.DefaultDateTimeKind; + _autoFakerConfig.Locale = locale; + return builder; } - internal TBuilder WithRepeatCount(Func? count, TBuilder builder) + internal TBuilder WithRepeatCount(int count, TBuilder builder) { - FakerConfig.RepeatCount = count ?? AutoFakerConfig.DefaultRepeatCount; + _autoFakerConfig.RepeatCount = count; + return builder; } - internal TBuilder WithDataTableRowCount(Func? count, TBuilder builder) + internal TBuilder WithDataTableRowCount(int count, TBuilder builder) { - FakerConfig.DataTableRowCount = count ?? AutoFakerConfig.DefaultDataTableRowCount; + _autoFakerConfig.DataTableRowCount = count; + return builder; } - internal TBuilder WithRecursiveDepth(Func? depth, TBuilder builder) + internal TBuilder WithRecursiveDepth(int depth, TBuilder builder) { - FakerConfig.RecursiveDepth = depth ?? AutoFakerConfig.DefaultRecursiveDepth; + _autoFakerConfig.RecursiveDepth = depth; + return builder; } - internal TBuilder WithTreeDepth(Func? depth, TBuilder builder) + internal TBuilder WithTreeDepth(int? depth, TBuilder builder) { - FakerConfig.TreeDepth = depth ?? AutoFakerConfig.DefaultTreeDepth; + _autoFakerConfig.TreeDepth = depth; + return builder; } private TBuilder WithBinder(AutoFakerBinder? fakerBinder, TBuilder builder) { - FakerConfig.FakerBinder = fakerBinder ?? new AutoFakerBinder(); + _autoFaker.Binder = fakerBinder; + return builder; } internal TBuilder WithFaker(Faker faker, TBuilder builder) { - FakerConfig.Faker = faker; + _autoFaker.Faker = faker; return builder; } internal TBuilder WithSkip(Type type, TBuilder builder) { - bool existing = FakerConfig.SkipTypes.Any(t => t == type); + _autoFakerConfig.SkipTypes ??= []; - if (!existing) - FakerConfig.SkipTypes.Add(type); + _autoFakerConfig.SkipTypes.Add(type); return builder; } @@ -164,10 +140,13 @@ internal TBuilder WithSkip(Type type, string memberName, TBuilder buil return builder; var path = $"{type.FullName}.{memberName}"; - bool existing = FakerConfig.SkipPaths.Any(s => s == path); + + _autoFakerConfig.SkipPaths ??= []; + + bool existing = _autoFakerConfig.SkipPaths.Any(s => s == path); if (!existing) - FakerConfig.SkipPaths.Add(path); + _autoFakerConfig.SkipPaths.Add(path); return builder; } @@ -177,17 +156,17 @@ internal TBuilder WithSkip(string memberName, TBuilder builder) return WithSkip(typeof(TType), memberName, builder); } - internal TBuilder WithOverride(GeneratorOverride? generatorOverride, TBuilder builder) + internal TBuilder WithOverride(AutoFakerGeneratorOverride? autoFakerGeneratorOverride, TBuilder builder) { - if (generatorOverride == null) + if (autoFakerGeneratorOverride == null) return builder; - bool existing = FakerConfig.Overrides.Any(o => o == generatorOverride); + _autoFakerConfig.Overrides ??= []; + + bool existing = _autoFakerConfig.Overrides.Any(o => o == autoFakerGeneratorOverride); if (!existing) - { - FakerConfig.Overrides.Add(generatorOverride); - } + _autoFakerConfig.Overrides.Add(autoFakerGeneratorOverride); return builder; } diff --git a/src/Config/AutoFakerDefaultConfigOptions.cs b/src/Config/AutoFakerDefaultConfigOptions.cs new file mode 100644 index 0000000..5750904 --- /dev/null +++ b/src/Config/AutoFakerDefaultConfigOptions.cs @@ -0,0 +1,14 @@ +namespace Soenneker.Utils.AutoBogus.Config; + +public static class AutoFakerDefaultConfigOptions +{ + internal const string DefaultLocale = "en"; + internal const int GenerateAttemptsThreshold = 3; + + internal const int DefaultRepeatCount = 3; + internal const int DefaultDataTableRowCount = 15; + + internal const int DefaultRecursiveDepth = 2; + + internal static readonly int? DefaultTreeDepth = null; +} \ No newline at end of file diff --git a/src/Config/Base/IBaseAutoFakerConfigBuilder.cs b/src/Config/Base/IBaseAutoFakerConfigBuilder.cs index 1dedbe1..579c98d 100644 --- a/src/Config/Base/IBaseAutoFakerConfigBuilder.cs +++ b/src/Config/Base/IBaseAutoFakerConfigBuilder.cs @@ -1,5 +1,4 @@ using System; -using Bogus; using Soenneker.Utils.AutoBogus.Abstract; using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Generators; @@ -24,14 +23,14 @@ public interface IBaseAutoFakerConfigBuilder /// /// The dateTimeKind to use. /// The current configuration builder instance. - TBuilder WithDateTimeKind(Func dateTimeKind); + //TBuilder WithDateTimeKind(Func dateTimeKind); - /// - /// Registers the DateTimeKind to use when generating date and time values. - /// - /// The dateTimeKind to use. - /// The current configuration builder instance. - TBuilder WithDateTimeKind(DateTimeKind dateTimeKind); + ///// + ///// Registers the DateTimeKind to use when generating date and time values. + ///// + ///// The dateTimeKind to use. + ///// The current configuration builder instance. + //TBuilder WithDateTimeKind(DateTimeKind dateTimeKind); /// /// Registers the number of items to generate for a collection. @@ -45,7 +44,7 @@ public interface IBaseAutoFakerConfigBuilder /// /// The repeat count to use. /// The current configuration builder instance. - TBuilder WithRepeatCount(Func count); + //TBuilder WithRepeatCount(Func count); /// /// Registers the number of rows to generate in a . @@ -59,7 +58,7 @@ public interface IBaseAutoFakerConfigBuilder /// /// The row count to use. /// The current configuration builder instance. - TBuilder WithDataTableRowCount(Func count); + //TBuilder WithDataTableRowCount(Func count); /// /// Registers the depth to recursively generate. @@ -80,14 +79,14 @@ public interface IBaseAutoFakerConfigBuilder /// /// The recursive depth to use. /// The current configuration builder instance. - TBuilder WithRecursiveDepth(Func depth); + //TBuilder WithRecursiveDepth(Func depth); /// /// Registers the depth to generate the object tree /// /// The depth to use. /// The current configuration builder instance. - TBuilder WithTreeDepth(Func depth); + //TBuilder WithTreeDepth( int? depth); /// /// Registers a binder instance to use when generating values. @@ -101,7 +100,7 @@ public interface IBaseAutoFakerConfigBuilder /// /// The instance to use as the hub. /// The current configuration builder instance. - TBuilder WithFaker(Faker faker); + //TBuilder WithFaker(Faker faker); /// /// Registers a type to skip when generating values. @@ -129,7 +128,7 @@ public interface IBaseAutoFakerConfigBuilder /// /// Registers an override instance to use when generating values. /// - /// The instance to use. + /// The instance to use. /// The current configuration builder instance. - TBuilder WithOverride(GeneratorOverride generatorOverride); + TBuilder WithOverride(AutoFakerGeneratorOverride autoFakerGeneratorOverride); } \ No newline at end of file diff --git a/src/Context/AutoFakerContext.cs b/src/Context/AutoFakerContext.cs index 34c67e1..202e49e 100644 --- a/src/Context/AutoFakerContext.cs +++ b/src/Context/AutoFakerContext.cs @@ -2,62 +2,58 @@ using System.Collections.Generic; using Bogus; using Soenneker.Reflection.Cache.Types; -using Soenneker.Utils.AutoBogus.Abstract; using Soenneker.Utils.AutoBogus.Config; -using Soenneker.Utils.AutoBogus.Generators; using Soenneker.Utils.AutoBogus.Services; namespace Soenneker.Utils.AutoBogus.Context; /// -/// A class that provides context for a generate request. +/// A class that provides context for a generate request. A 'generate request' is a single call to `.Generate()` for example. /// public sealed class AutoFakerContext { /// /// The parent type of the type associated with the current generate request. /// - public Type ParentType { get; private set; } + public Type? ParentType; /// /// The type associated with the current generate request. /// - public Type GenerateType { get; private set; } + public Type? GenerateType; - public CachedType CachedType { get; private set; } + public CachedType CachedType; /// /// The name associated with the current generate request. /// - public string GenerateName { get; private set; } + public string GenerateName; /// /// The underlying instance used to generate random values. /// - public Faker Faker { get; } + public readonly Faker Faker; + + public readonly AutoFakerConfig Config; + + public readonly AutoFakerBinder Binder; /// /// The requested rule sets provided for the generate request. /// - public List RuleSets { get; internal set; } - - internal AutoFakerConfig AutoFakerConfig { get; } - - internal Stack TypesStack { get; } + public List RuleSets; - internal object Instance { get; set; } + internal readonly Stack TypesStack; - internal IAutoFakerBinder FakerBinder => AutoFakerConfig.FakerBinder; + internal object Instance; - internal List? Overrides => AutoFakerConfig.Overrides; - - internal AutoFakerContext(AutoFakerConfig autoFakerConfig, Type? type = null) + internal AutoFakerContext(AutoFakerConfig config, Faker faker, AutoFakerBinder binder, Type? type = null) { - AutoFakerConfig = autoFakerConfig; - - Faker = autoFakerConfig.Faker!; + TypesStack = new Stack(); + Config = config; - TypesStack = new Stack(); + Binder = binder; + Faker = faker; RuleSets = []; @@ -65,12 +61,12 @@ internal AutoFakerContext(AutoFakerConfig autoFakerConfig, Type? type = null) Setup(type); } - internal void Setup(Type parentType, Type generateType, string name) + internal void Setup(Type parentType, CachedType generateType, string name) { ParentType = parentType; - GenerateType = generateType; + GenerateType = generateType.Type; GenerateName = name; - CachedType = CacheService.Cache.GetCachedType(generateType); + CachedType = generateType; } internal void Setup(Type generateType) diff --git a/src/Context/AutoFakerContextOverride.cs b/src/Context/AutoFakerOverrideContext.cs similarity index 91% rename from src/Context/AutoFakerContextOverride.cs rename to src/Context/AutoFakerOverrideContext.cs index 036e91a..d13fb7c 100644 --- a/src/Context/AutoFakerContextOverride.cs +++ b/src/Context/AutoFakerOverrideContext.cs @@ -7,18 +7,8 @@ namespace Soenneker.Utils.AutoBogus.Context; /// /// A class that provides context when overriding a generate request. /// -public sealed class AutoFakerContextOverride +public sealed class AutoFakerOverrideContext { - internal AutoFakerContextOverride(AutoFakerContext generateContext) - { - GenerateContext = generateContext; - - GenerateType = GenerateContext.GenerateType; - GenerateName = GenerateContext.GenerateName; - Faker = GenerateContext.Faker; - RuleSets = GenerateContext.RuleSets; - } - /// /// The instance generated during the override. /// @@ -45,4 +35,14 @@ internal AutoFakerContextOverride(AutoFakerContext generateContext) public List RuleSets { get; } internal AutoFakerContext GenerateContext { get; } + + internal AutoFakerOverrideContext(AutoFakerContext generateContext) + { + GenerateContext = generateContext; + + GenerateType = GenerateContext.GenerateType; + GenerateName = GenerateContext.GenerateName; + Faker = GenerateContext.Faker; + RuleSets = GenerateContext.RuleSets; + } } \ No newline at end of file diff --git a/src/Enums/GenericCollectionType.cs b/src/Enums/GenericCollectionType.cs index 54daa83..6e83886 100644 --- a/src/Enums/GenericCollectionType.cs +++ b/src/Enums/GenericCollectionType.cs @@ -1,4 +1,5 @@ using Ardalis.SmartEnum; +#pragma warning disable CA2211 namespace Soenneker.Utils.AutoBogus.Enums; diff --git a/src/Extensions/AutoConfigBuilderExtension.cs b/src/Extensions/AutoConfigBuilderExtension.cs index 30a6788..15630d7 100644 --- a/src/Extensions/AutoConfigBuilderExtension.cs +++ b/src/Extensions/AutoConfigBuilderExtension.cs @@ -13,8 +13,6 @@ namespace Soenneker.Utils.AutoBogus.Extensions; /// public static class AutoConfigBuilderExtension { - #region WithBinder - /// /// Registers a binder type to use when generating values. /// @@ -54,10 +52,6 @@ public static IAutoFakerConfigBuilder WithBinder(this IAutoFakerConfigB return builder?.WithBinder(binder); } - #endregion - - #region WithSkip - /// /// Registers a type to skip when generating values. /// @@ -66,7 +60,7 @@ public static IAutoFakerConfigBuilder WithBinder(this IAutoFakerConfigB /// The current configuration builder instance. public static IAutoFakerDefaultConfigBuilder WithSkip(this IAutoFakerDefaultConfigBuilder builder) { - Type? type = typeof(TType); + Type type = typeof(TType); return builder?.WithSkip(type); } @@ -78,7 +72,7 @@ public static IAutoFakerDefaultConfigBuilder WithSkip(this IAutoFakerDefa /// The current configuration builder instance. public static IAutoGenerateConfigBuilder WithSkip(this IAutoGenerateConfigBuilder builder) { - Type? type = typeof(TType); + Type type = typeof(TType); return builder?.WithSkip(type); } @@ -90,7 +84,7 @@ public static IAutoGenerateConfigBuilder WithSkip(this IAutoGenerateConfi /// The current configuration builder instance. public static IAutoFakerConfigBuilder WithSkip(this IAutoFakerConfigBuilder builder) { - Type? type = typeof(TType); + Type type = typeof(TType); return builder?.WithSkip(type); } @@ -133,10 +127,6 @@ public static IAutoFakerConfigBuilder WithSkip(this IAutoFakerConfigBuild return builder?.WithSkip(memberName); } - #endregion - - #region WithOverride - /// /// Registers an override instance to use when generating values. /// @@ -144,9 +134,9 @@ public static IAutoFakerConfigBuilder WithSkip(this IAutoFakerConfigBuild /// The current configuration builder instance. /// A handler used to generate the override. /// The current configuration builder instance. - public static IAutoFakerDefaultConfigBuilder WithOverride(this IAutoFakerDefaultConfigBuilder builder, Func generator) + public static IAutoFakerDefaultConfigBuilder WithOverride(this IAutoFakerDefaultConfigBuilder builder, Func generator) { - var generatorOverride = new GeneratorTypeOverride(generator); + var generatorOverride = new AutoFakerGeneratorTypeOverride(generator); return builder?.WithOverride(generatorOverride); } @@ -157,9 +147,9 @@ public static IAutoFakerDefaultConfigBuilder WithOverride(this IAutoFaker /// The current configuration builder instance. /// A handler used to generate the override. /// The current configuration builder instance. - public static IAutoGenerateConfigBuilder WithOverride(this IAutoGenerateConfigBuilder builder, Func generator) + public static IAutoGenerateConfigBuilder WithOverride(this IAutoGenerateConfigBuilder builder, Func generator) { - var generatorOverride = new GeneratorTypeOverride(generator); + var generatorOverride = new AutoFakerGeneratorTypeOverride(generator); return builder?.WithOverride(generatorOverride); } @@ -170,9 +160,9 @@ public static IAutoGenerateConfigBuilder WithOverride(this IAutoGenerateC /// The current configuration builder instance. /// A handler used to generate the override. /// The current configuration builder instance. - public static IAutoFakerConfigBuilder WithOverride(this IAutoFakerConfigBuilder builder, Func generator) + public static IAutoFakerConfigBuilder WithOverride(this IAutoFakerConfigBuilder builder, Func generator) { - var generatorOverride = new GeneratorTypeOverride(generator); + var generatorOverride = new AutoFakerGeneratorTypeOverride(generator); return builder?.WithOverride(generatorOverride); } @@ -185,10 +175,10 @@ public static IAutoFakerConfigBuilder WithOverride(this IAutoFakerConfigB /// The member to override. /// A handler used to generate the override. /// The current configuration builder instance. - public static IAutoFakerDefaultConfigBuilder WithOverride(this IAutoFakerDefaultConfigBuilder builder, Expression> member, Func generator) + public static IAutoFakerDefaultConfigBuilder WithOverride(this IAutoFakerDefaultConfigBuilder builder, Expression> member, Func generator) { string? memberName = GetMemberName(member); - var generatorOverride = new GeneratorMemberOverride(memberName, generator); + var generatorOverride = new AutoFakerGeneratorMemberOverride(memberName, generator); return builder?.WithOverride(generatorOverride); } @@ -202,10 +192,10 @@ public static IAutoFakerDefaultConfigBuilder WithOverride(this IA /// The member to override. /// A handler used to generate the override. /// The current configuration builder instance. - public static IAutoGenerateConfigBuilder WithOverride(this IAutoGenerateConfigBuilder builder, Expression> member, Func generator) + public static IAutoGenerateConfigBuilder WithOverride(this IAutoGenerateConfigBuilder builder, Expression> member, Func generator) { string? memberName = GetMemberName(member); - var generatorOverride = new GeneratorMemberOverride(memberName, generator); + var generatorOverride = new AutoFakerGeneratorMemberOverride(memberName, generator); return builder?.WithOverride(generatorOverride); } @@ -219,16 +209,14 @@ public static IAutoGenerateConfigBuilder WithOverride(this IAutoG /// The member to override. /// A handler used to generate the override. /// The current configuration builder instance. - public static IAutoFakerConfigBuilder WithOverride(this IAutoFakerConfigBuilder builder, Expression> member, Func generator) + public static IAutoFakerConfigBuilder WithOverride(this IAutoFakerConfigBuilder builder, Expression> member, Func generator) { string? memberName = GetMemberName(member); - var generatorOverride = new GeneratorMemberOverride(memberName, generator); + var generatorOverride = new AutoFakerGeneratorMemberOverride(memberName, generator); return builder?.WithOverride(generatorOverride); } - #endregion - private static string? GetMemberName(Expression>? member) { if (member == null) diff --git a/src/Extensions/AutoGenerateContextExtension.cs b/src/Extensions/AutoGenerateContextExtension.cs index fbabf17..6ef784b 100644 --- a/src/Extensions/AutoGenerateContextExtension.cs +++ b/src/Extensions/AutoGenerateContextExtension.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using Soenneker.Utils.AutoBogus.Config; using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Generators; @@ -28,8 +27,9 @@ public static class AutoGenerateContextExtension context.Setup(typeof(TType)); // Get the type generator and return a value - IAutoFakerGenerator generator = GeneratorFactory.GetGenerator(context); - return (TType) generator.Generate(context); + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.GetGenerator(context); + object generatedInstance = generator.Generate(context); + return (TType)generatedInstance; } /// @@ -70,61 +70,57 @@ public static List GenerateUniqueMany(this AutoFakerContext? conte return items; } - /// - /// Populates the provided instance with generated values. - /// - /// The type of instance to populate. - /// The instance for the current generate request. - /// The instance to populate. - public static void Populate(this AutoFakerContext? context, TType instance) + internal static void GenerateMany(AutoFakerContext context, int? count, List items, bool unique, int attempts = 1, Func? generate = null) { - context?.FakerBinder.PopulateInstance(instance, context); - } + // Apply any defaults + count ??= AutoFakerDefaultConfigOptions.DefaultRepeatCount; - internal static void GenerateMany(AutoFakerContext context, int? count, List items, bool unique, int attempt = 1, Func? generate = null) - { - while (true) + generate ??= context.Generate; + + // Generate a list of items + int? required = count - items.Count; + + for (var i = 0; i < required; i++) { - // Apply any defaults - count ??= context.AutoFakerConfig.RepeatCount.Invoke(context); - - generate ??= context.Generate; - - // Generate a list of items - int? required = count - items.Count; - - for (var index = 0; index < required; index++) - { - TType? item = generate.Invoke(); - - // Ensure the generated value is not null (which means the type couldn't be generated) - if (item != null) - { - items.Add(item); - } - } - - if (unique) - { - // Remove any duplicates and generate more to match the required count - List filtered = items.Distinct().ToList(); - - if (filtered.Count < count) - { - // To maintain the items reference, clear and reapply the filtered list - items.Clear(); - items.AddRange(filtered); - - // Only continue to generate more if the attempts threshold is not reached - if (attempt < AutoFakerConfig.GenerateAttemptsThreshold) - { - attempt += 1; - continue; - } - } - } - - break; + TType item = generate.Invoke(); + + // Ensure the generated value is not null (which means the type couldn't be generated) + if (item != null) + items.Add(item); } + + if (!unique) + return; + + var hashSet = new HashSet(); + + for (var i = 0; i < items.Count; i++) + { + TType item = items[i]; + hashSet.Add(item); + } + + if (hashSet.Count == items.Count) + return; + + for (var i = 0; i < attempts; i++) + { + TType item = generate.Invoke(); + + // Ensure the generated value is not null (which means the type couldn't be generated) + if (item != null) + hashSet.Add(item); + + if (hashSet.Count != count) + continue; + + // To maintain the items reference, clear and reapply the filtered list + items.Clear(); + items.AddRange(hashSet); + return; + } + + items.Clear(); + items.AddRange(hashSet); } } \ No newline at end of file diff --git a/src/Extensions/AutoGenerateOverrideContextExtension.cs b/src/Extensions/AutoGenerateOverrideContextExtension.cs index 5a4afed..0960857 100644 --- a/src/Extensions/AutoGenerateOverrideContextExtension.cs +++ b/src/Extensions/AutoGenerateOverrideContextExtension.cs @@ -1,6 +1,3 @@ -using System.Collections.Generic; -using Soenneker.Utils.AutoBogus.Context; - namespace Soenneker.Utils.AutoBogus.Extensions; /// @@ -8,49 +5,5 @@ namespace Soenneker.Utils.AutoBogus.Extensions; /// public static class AutoGenerateOverrideContextExtension { - /// - /// Generates an instance of type . - /// - /// The instance type to generate. - /// The instance for the current generate request. - /// The generated instance. - public static TType Generate(this AutoFakerContextOverride context) - { - return context == null ? default : context.GenerateContext.Generate(); - } - - /// - /// Generates a collection of instances of type . - /// - /// The instance type to generate. - /// The instance for the current generate request. - /// The number of instances to generate. - /// The generated collection of instances. - public static List GenerateMany(this AutoFakerContextOverride context, int? count = null) - { - return context?.GenerateContext.GenerateMany(count) ?? new List(); - } - - /// - /// Generates a collection of unique instances of type . - /// - /// The instance type to generate. - /// The instance for the current generate request. - /// The number of instances to generate. - /// The generated collection of unique instances. - public static List GenerateUniqueMany(this AutoFakerContextOverride context, int? count = null) - { - return context?.GenerateContext.GenerateUniqueMany(count) ?? new List(); - } - /// - /// Populates the provided instance with generated values. - /// - /// The type of instance to populate. - /// The instance for the current generate request. - /// The instance to populate. - public static void Populate(this AutoFakerContextOverride context, TType instance) - { - context?.GenerateContext.Populate(instance); - } } \ No newline at end of file diff --git a/src/Extensions/CachedTypeExtension.cs b/src/Extensions/CachedTypeExtension.cs index f75abec..a4b88e3 100644 --- a/src/Extensions/CachedTypeExtension.cs +++ b/src/Extensions/CachedTypeExtension.cs @@ -1,15 +1,39 @@ using Soenneker.Reflection.Cache.Types; +using Soenneker.Utils.AutoBogus.Services; using System; namespace Soenneker.Utils.AutoBogus.Extensions; internal static class CachedTypeExtension { - public static Type[] GetAddMethodArgumentTypes(this CachedType type) + private static readonly CachedType _object = CacheService.Cache.GetCachedType(typeof(object)); + + public static CachedType[] GetAddMethodArgumentTypes(this CachedType type) { if (!type.IsGenericType) - return [typeof(object)]; + return [_object]; + + return type.GetCachedGenericArguments()!; + } + + internal static bool IsCollection(this CachedType type) + { + return IsGenericType(type, "ICollection`1"); + } + + private static bool IsGenericType(CachedType cachedType, string interfaceTypeName) + { + if (cachedType.Type.Name == interfaceTypeName) + return true; + + Type[] interfaces = cachedType.GetInterfaces()!; + + foreach (Type i in interfaces) + { + if (i.Name == interfaceTypeName) + return true; + } - return type.GetGenericArguments()!; + return false; } } \ No newline at end of file diff --git a/src/Extensions/TypeArrayExtension.cs b/src/Extensions/TypeArrayExtension.cs index 277bf8d..e98bfcc 100644 --- a/src/Extensions/TypeArrayExtension.cs +++ b/src/Extensions/TypeArrayExtension.cs @@ -6,87 +6,97 @@ namespace Soenneker.Utils.AutoBogus.Extensions; internal static class TypeArrayExtension { - internal static (CachedType?, GenericCollectionType?) GetTypeOfGenericCollectionFromInterfaceTypes(this List types) + internal static (CachedType?, GenericCollectionType?) GetTypeOfGenericCollectionFromInterfaceTypes(this List cachedTypes) { - if (types.Count == 0) + if (cachedTypes.Count == 0) return (null, null); GenericCollectionType genericCollectionType = GenericCollectionType.Unknown; CachedType? returnType = null; - foreach (CachedType type in types) + for (var i = 0; i < cachedTypes.Count; i++) { - switch (type.Type.Name) + CachedType cachedType = cachedTypes[i]; + switch (cachedType.Type.Name) { case "SortedList`2": - return (type, GenericCollectionType.SortedList); + return (cachedType, GenericCollectionType.SortedList); case "Dictionary`2": - return (type, GenericCollectionType.Dictionary); + return (cachedType, GenericCollectionType.Dictionary); case "ReadOnlyDictionary`2": - return (type, GenericCollectionType.ReadOnlyDictionary); + return (cachedType, GenericCollectionType.ReadOnlyDictionary); case "IDictionary`2": if (genericCollectionType < GenericCollectionType.Dictionary) { genericCollectionType = GenericCollectionType.Dictionary; - returnType = type; + returnType = cachedType; } + break; case "IImmutableDictionary`2": if (genericCollectionType < GenericCollectionType.ImmutableDictionary) { genericCollectionType = GenericCollectionType.ImmutableDictionary; - returnType = type; + returnType = cachedType; } + break; case "IReadOnlyDictionary`2": if (genericCollectionType < GenericCollectionType.ReadOnlyDictionary) { genericCollectionType = GenericCollectionType.ReadOnlyDictionary; - returnType = type; + returnType = cachedType; } + break; case "IReadOnlylist`1": if (genericCollectionType < GenericCollectionType.ReadOnlyList) { genericCollectionType = GenericCollectionType.ReadOnlyList; - returnType = type; + returnType = cachedType; } + break; case "Ilist`1": if (genericCollectionType < GenericCollectionType.ListType) { genericCollectionType = GenericCollectionType.ListType; - returnType = type; + returnType = cachedType; } + break; case "ISet`1": if (genericCollectionType < GenericCollectionType.Set) { genericCollectionType = GenericCollectionType.Set; - returnType = type; + returnType = cachedType; } + break; case "IReadOnlyCollection`1": if (genericCollectionType < GenericCollectionType.ReadOnlyCollection) { genericCollectionType = GenericCollectionType.ReadOnlyCollection; - returnType = type; + returnType = cachedType; } + break; case "ICollection`1": if (genericCollectionType < GenericCollectionType.Collection) { genericCollectionType = GenericCollectionType.Collection; - returnType = type; + returnType = cachedType; } + break; case "IEnumerable`1": if (genericCollectionType < GenericCollectionType.Enumerable) { genericCollectionType = GenericCollectionType.Enumerable; - returnType = type; + returnType = cachedType; } + break; } } diff --git a/src/Extensions/TypeExtension.cs b/src/Extensions/TypeExtension.cs deleted file mode 100644 index ae4361e..0000000 --- a/src/Extensions/TypeExtension.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Dynamic; -using Soenneker.Reflection.Cache.Types; - -namespace Soenneker.Utils.AutoBogus.Extensions; - -public static class TypeExtension -{ - internal static bool IsExpandoObject(this CachedType type) - { - return type.Type == typeof(ExpandoObject); - } - - internal static bool IsDictionary(this CachedType type) - { - return IsGenericType(type, "IDictionary`2"); - } - - internal static bool IsReadOnlyDictionary(this CachedType type) - { - return IsGenericType(type, "IReadOnlyDictionary`2"); - } - - internal static bool IsCollection(this CachedType type) - { - return IsGenericType(type, "ICollection`1"); - } - - internal static bool IsEnumerable(this CachedType type) - { - return IsGenericType(type, "IEnumerable`1"); - } - - private static bool IsGenericType(CachedType cachedType, string interfaceTypeName) - { - if (cachedType.Type.Name == interfaceTypeName) - return true; - - Type[] interfaces = cachedType.GetInterfaces()!; - - foreach (Type i in interfaces) - { - if (i.Name == interfaceTypeName) - return true; - } - - return false; - } -} \ No newline at end of file diff --git a/src/Generators/Abstract/IAutoFakerGenerator.cs b/src/Generators/Abstract/IAutoFakerGenerator.cs index 7065b33..2d913be 100644 --- a/src/Generators/Abstract/IAutoFakerGenerator.cs +++ b/src/Generators/Abstract/IAutoFakerGenerator.cs @@ -4,5 +4,5 @@ namespace Soenneker.Utils.AutoBogus.Generators.Abstract; internal interface IAutoFakerGenerator { - object Generate(AutoFakerContext context); + object? Generate(AutoFakerContext context); } \ No newline at end of file diff --git a/src/Generators/GeneratorFactory.cs b/src/Generators/AutoFakerGeneratorFactory.cs similarity index 54% rename from src/Generators/GeneratorFactory.cs rename to src/Generators/AutoFakerGeneratorFactory.cs index b9dc142..fcc57b8 100644 --- a/src/Generators/GeneratorFactory.cs +++ b/src/Generators/AutoFakerGeneratorFactory.cs @@ -1,56 +1,35 @@ using System; using System.Collections.Generic; -using System.Net; using Soenneker.Reflection.Cache.Types; using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Enums; -using Soenneker.Utils.AutoBogus.Extensions; using Soenneker.Utils.AutoBogus.Generators.Abstract; using Soenneker.Utils.AutoBogus.Generators.Types; +using Soenneker.Utils.AutoBogus.Services; using Soenneker.Utils.AutoBogus.Utils; namespace Soenneker.Utils.AutoBogus.Generators; -internal static class GeneratorFactory +public static class AutoFakerGeneratorFactory { - internal static readonly IDictionary Generators = new Dictionary - { - {typeof(bool), new BoolGenerator()}, - {typeof(byte), new ByteGenerator()}, - {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()}, - {typeof(Guid), new GuidGenerator()}, - {typeof(int), new IntGenerator()}, - {typeof(IPAddress), new IpAddressGenerator()}, - {typeof(long), new LongGenerator()}, - {typeof(sbyte), new SByteGenerator()}, - {typeof(short), new ShortGenerator()}, - {typeof(string), new StringGenerator()}, - {typeof(uint), new UIntGenerator()}, - {typeof(ulong), new ULongGenerator()}, - {typeof(Uri), new UriGenerator()}, - {typeof(ushort), new UShortGenerator()} - }; - internal static IAutoFakerGenerator GetGenerator(AutoFakerContext context) { - IAutoFakerGenerator generator = ResolveGenerator(context); + IAutoFakerGenerator? cachedGenerator = GeneratorService.GetGenerator(context.CachedType); + + if (cachedGenerator != null) + return cachedGenerator; + + IAutoFakerGenerator generator = CreateGenerator(context); - List? overrides = null; + List? overrides = null; - if (context.Overrides != null) + if (context.Config.Overrides != null) { overrides = []; - for (var i = 0; i < context.Overrides.Count; i++) + for (var i = 0; i < context.Config.Overrides.Count; i++) { - GeneratorOverride? o = context.Overrides[i]; + AutoFakerGeneratorOverride o = context.Config.Overrides[i]; if (o.CanOverride(context)) overrides.Add(o); @@ -58,34 +37,39 @@ internal static IAutoFakerGenerator GetGenerator(AutoFakerContext context) } if (overrides == null || overrides.Count == 0) + { + GeneratorService.SetGenerator(context.CachedType, generator); return generator; + } + + var newOverrideGenerator = new AutoFakerGeneratorOverrideInvoker(generator, overrides); - return new GeneratorOverrideInvoker(generator, overrides); + GeneratorService.SetGenerator(context.CachedType, newOverrideGenerator); + return newOverrideGenerator; } - internal static IAutoFakerGenerator ResolveGenerator(AutoFakerContext context) + internal static IAutoFakerGenerator CreateGenerator(AutoFakerContext context) { + IAutoFakerGenerator? fundamentalGenerator = GeneratorService.GetFundamentalGenerator(context.CachedType); + + if (fundamentalGenerator != null) + return fundamentalGenerator; + Type? type = context.GenerateType; // Need check if the type is an in/out parameter and adjusted accordingly - if (type.IsByRef) + if (context.CachedType.IsByRef) { type = type.GetElementType(); } // Do some type -> generator mapping - if (type.IsArray) + if (context.CachedType.IsArray) { type = type.GetElementType(); return CreateGenericGenerator(typeof(ArrayGenerator<>), type); } - // Resolve the generator from the type - if (Generators.TryGetValue(type, out IAutoFakerGenerator? generator)) - { - return generator; - } - if (context.CachedType.IsEnum) { return CreateGenericGenerator(typeof(EnumGenerator<>), type); @@ -99,7 +83,7 @@ internal static IAutoFakerGenerator ResolveGenerator(AutoFakerContext context) // Check if an expando object needs to generator // This actually means an existing dictionary needs to be populated - if (context.CachedType.IsExpandoObject()) + if (context.CachedType.IsExpandoObject) { return new ExpandoObjectGenerator(); } @@ -114,43 +98,43 @@ internal static IAutoFakerGenerator ResolveGenerator(AutoFakerContext context) 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); - } - case nameof(GenericCollectionType.Enumerable): - { - 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); + return CreateGenericGenerator(typeof(SetGenerator<>), elementType); + } + case nameof(GenericCollectionType.Enumerable): + { + 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; } - - break; - } } } @@ -178,6 +162,9 @@ 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); + + var cached = (IAutoFakerGenerator)CacheService.Cache.GetCachedType(type).CreateInstance(); + return cached; + // return (IAutoFakerGenerator) Activator.CreateInstance(type); } } \ No newline at end of file diff --git a/src/Generators/GeneratorMemberOverride.cs b/src/Generators/AutoFakerGeneratorMemberOverride.cs similarity index 69% rename from src/Generators/GeneratorMemberOverride.cs rename to src/Generators/AutoFakerGeneratorMemberOverride.cs index 7748bd9..f126d47 100644 --- a/src/Generators/GeneratorMemberOverride.cs +++ b/src/Generators/AutoFakerGeneratorMemberOverride.cs @@ -3,9 +3,9 @@ namespace Soenneker.Utils.AutoBogus.Generators; -internal sealed class GeneratorMemberOverride : GeneratorOverride +internal sealed class AutoFakerGeneratorMemberOverride : AutoFakerGeneratorOverride { - internal GeneratorMemberOverride(string memberName, Func generator) + internal AutoFakerGeneratorMemberOverride(string memberName, Func generator) { if (string.IsNullOrWhiteSpace(memberName)) { @@ -19,14 +19,14 @@ internal GeneratorMemberOverride(string memberName, Func Generator { get; } + private Func Generator { get; } public override bool CanOverride(AutoFakerContext context) { return context.ParentType == Type && MemberName.Equals(context.GenerateName, StringComparison.OrdinalIgnoreCase); } - public override void Generate(AutoFakerContextOverride context) + public override void Generate(AutoFakerOverrideContext context) { context.Instance = Generator.Invoke(context); } diff --git a/src/Generators/GeneratorOverride.cs b/src/Generators/AutoFakerGeneratorOverride.cs similarity index 77% rename from src/Generators/GeneratorOverride.cs rename to src/Generators/AutoFakerGeneratorOverride.cs index 32b6fd1..410cbe3 100644 --- a/src/Generators/GeneratorOverride.cs +++ b/src/Generators/AutoFakerGeneratorOverride.cs @@ -5,7 +5,7 @@ namespace Soenneker.Utils.AutoBogus.Generators; /// /// A class for overriding generate requests. /// -public abstract class GeneratorOverride +public abstract class AutoFakerGeneratorOverride { /// /// Gets whether a pre-initialized instance is required. Defaults to true. @@ -25,6 +25,6 @@ public virtual bool Preinitialize /// /// Generates an override instance of a given type. /// - /// The instance for the current generate request. - public abstract void Generate(AutoFakerContextOverride context); + /// The instance for the current generate request. + public abstract void Generate(AutoFakerOverrideContext context); } \ No newline at end of file diff --git a/src/Generators/GeneratorOverrideInvoker.cs b/src/Generators/AutoFakerGeneratorOverrideInvoker.cs similarity index 68% rename from src/Generators/GeneratorOverrideInvoker.cs rename to src/Generators/AutoFakerGeneratorOverrideInvoker.cs index 721325a..594ca54 100644 --- a/src/Generators/GeneratorOverrideInvoker.cs +++ b/src/Generators/AutoFakerGeneratorOverrideInvoker.cs @@ -4,23 +4,24 @@ namespace Soenneker.Utils.AutoBogus.Generators; -internal sealed class GeneratorOverrideInvoker +internal sealed class AutoFakerGeneratorOverrideInvoker : IAutoFakerGenerator { - internal GeneratorOverrideInvoker(IAutoFakerGenerator generator, List overrides) + internal AutoFakerGeneratorOverrideInvoker(IAutoFakerGenerator generator, List overrides) { Generator = generator; Overrides = overrides; } internal IAutoFakerGenerator Generator { get; } - internal List Overrides { get; } + + internal List Overrides { get; } object IAutoFakerGenerator.Generate(AutoFakerContext context) { - var overrideContext = new AutoFakerContextOverride(context); + var overrideContext = new AutoFakerOverrideContext(context); - foreach (GeneratorOverride? generatorOverride in Overrides) + foreach (AutoFakerGeneratorOverride generatorOverride in Overrides) { // Check if an initialized instance is needed if (generatorOverride.Preinitialize && overrideContext.Instance == null) diff --git a/src/Generators/GeneratorTypeOverride.cs b/src/Generators/AutoFakerGeneratorTypeOverride.cs similarity index 60% rename from src/Generators/GeneratorTypeOverride.cs rename to src/Generators/AutoFakerGeneratorTypeOverride.cs index 0956c43..d8d0863 100644 --- a/src/Generators/GeneratorTypeOverride.cs +++ b/src/Generators/AutoFakerGeneratorTypeOverride.cs @@ -3,9 +3,9 @@ namespace Soenneker.Utils.AutoBogus.Generators; -internal sealed class GeneratorTypeOverride : GeneratorOverride +internal sealed class AutoFakerGeneratorTypeOverride : AutoFakerGeneratorOverride { - internal GeneratorTypeOverride(Func generator) + internal AutoFakerGeneratorTypeOverride(Func generator) { Type = typeof(TType); Generator = generator ?? throw new ArgumentNullException(nameof(generator)); @@ -13,14 +13,14 @@ internal GeneratorTypeOverride(Func generator) private Type Type { get; } - private Func Generator { get; } + private Func Generator { get; } public override bool CanOverride(AutoFakerContext context) { return context.GenerateType == Type; } - public override void Generate(AutoFakerContextOverride context) + public override void Generate(AutoFakerOverrideContext context) { context.Instance = Generator.Invoke(context); } diff --git a/src/Generators/Types/DataSetGenerator.cs b/src/Generators/Types/DataSetGenerator.cs index 048b731..47e023e 100644 --- a/src/Generators/Types/DataSetGenerator.cs +++ b/src/Generators/Types/DataSetGenerator.cs @@ -58,7 +58,7 @@ public override object Generate(AutoFakerContext context) { var dataSet = _dataSetType.CreateInstance(); - List? allTables = dataSet.Tables.OfType().ToList(); + List allTables = dataSet.Tables.OfType().ToList(); var populatedTables = new HashSet(); while (allTables.Count > 0) @@ -67,9 +67,9 @@ public override object Generate(AutoFakerContext context) for (int i = 0; i < allTables.Count; i++) { - DataTable? table = allTables[i]; + DataTable table = allTables[i]; - IEnumerable? referencedTables = table.Constraints + IEnumerable referencedTables = table.Constraints .OfType() .Select(constraint => constraint.RelatedTable); @@ -85,7 +85,7 @@ public override object Generate(AutoFakerContext context) context.Instance = table; - tableGenerator.PopulateRows(table, context); + DataTableGenerator.PopulateRows(table, context); madeProgress = true; diff --git a/src/Generators/Types/DataTableGenerator.cs b/src/Generators/Types/DataTableGenerator.cs index 332afb1..76df3a7 100644 --- a/src/Generators/Types/DataTableGenerator.cs +++ b/src/Generators/Types/DataTableGenerator.cs @@ -42,7 +42,7 @@ public static bool TryCreateGenerator(CachedType tableType, out DataTableGenerat generator = new UntypedDataTableGenerator(); else if (IsTypedDataTableType(tableType, out Type? rowType)) { - Type? generatorType = typeof(TypedDataTableGenerator<,>).MakeGenericType(tableType.Type, rowType); + Type generatorType = typeof(TypedDataTableGenerator<,>).MakeGenericType(tableType.Type, rowType); generator = (DataTableGenerator) Activator.CreateInstance(generatorType); } @@ -52,7 +52,7 @@ public static bool TryCreateGenerator(CachedType tableType, out DataTableGenerat public object Generate(AutoFakerContext context) { - DataTable? table = CreateTable(context); + DataTable table = CreateTable(context); context.Instance = table; @@ -67,16 +67,16 @@ class ConstrainedColumnInformation public DataColumn RelatedColumn; } - public void PopulateRows(DataTable table, AutoFakerContext context) + public static void PopulateRows(DataTable table, AutoFakerContext context) { bool rowCountIsSpecified = false; int rowCount = -1; - if (context.AutoFakerConfig.DataTableRowCount != null) + if (context.Config.DataTableRowCount != null) { rowCountIsSpecified = true; - rowCount = context.AutoFakerConfig.DataTableRowCount(context); + rowCount = context.Config.DataTableRowCount; } if (rowCount < 0) @@ -94,8 +94,8 @@ public void PopulateRows(DataTable table, AutoFakerContext context) for (int i = 0; i < foreignKey.Columns.Length; i++) { - DataColumn? column = foreignKey.Columns[i]; - DataColumn? relatedColumn = foreignKey.RelatedColumns[i]; + DataColumn column = foreignKey.Columns[i]; + DataColumn relatedColumn = foreignKey.RelatedColumns[i]; if (constrainedColumns.ContainsKey(column)) throw new Exception($"Column is constrained in multiple foreign key relationships simultaneously: {column.ColumnName} in DataTable {table.TableName}"); @@ -137,7 +137,7 @@ public void PopulateRows(DataTable table, AutoFakerContext context) } } - List? allConstraints = referencedRowByConstraint.Keys.ToList(); + List allConstraints = referencedRowByConstraint.Keys.ToList(); while (rowCount > 0) { @@ -169,7 +169,7 @@ public void PopulateRows(DataTable table, AutoFakerContext context) } } - private object GenerateColumnValue(DataColumn dataColumn, AutoFakerContext context) + private static object GenerateColumnValue(DataColumn dataColumn, AutoFakerContext context) { switch (Type.GetTypeCode(dataColumn.DataType)) { diff --git a/src/Generators/Types/DateTimeGenerator.cs b/src/Generators/Types/DateTimeGenerator.cs index b687f6b..6cccf58 100644 --- a/src/Generators/Types/DateTimeGenerator.cs +++ b/src/Generators/Types/DateTimeGenerator.cs @@ -10,8 +10,10 @@ internal sealed class DateTimeGenerator { object IAutoFakerGenerator.Generate(AutoFakerContext context) { - return context.AutoFakerConfig.DateTimeKind.Invoke(context) == DateTimeKind.Utc - ? context.Faker.Date.Recent().ToUniversalTime() - : context.Faker.Date.Recent(); + return context.Faker.Date.Recent(); + + //return context.Config.DateTimeKind.Invoke(context) == DateTimeKind.Utc + // ? context.Faker.Date.Recent().ToUniversalTime() + // : context.Faker.Date.Recent(); } } \ No newline at end of file diff --git a/src/Generators/Types/DictionaryGenerator.cs b/src/Generators/Types/DictionaryGenerator.cs index 6a353c1..d358318 100644 --- a/src/Generators/Types/DictionaryGenerator.cs +++ b/src/Generators/Types/DictionaryGenerator.cs @@ -13,13 +13,22 @@ object IAutoFakerGenerator.Generate(AutoFakerContext context) { // Create an instance of a dictionary (public and non-public) IDictionary items; - try + + if (context.CachedType.IsInterface || context.GenerateType.Name == "Dictionary`2") { - items = (IDictionary)Activator.CreateInstance(context.GenerateType, true); + items = new Dictionary(); } - catch + else { - items = new Dictionary(); + try + { + // items = (IDictionary)Activator.CreateInstance(context.GenerateType, true); + items = (IDictionary)context.CachedType.CreateInstance(); //(IDictionary)Activator.CreateInstance(context.GenerateType, true); + } + catch (Exception e) + { + items = new Dictionary(); + } } // Get a list of keys diff --git a/src/Generators/Types/ExpandoObjectGenerator.cs b/src/Generators/Types/ExpandoObjectGenerator.cs index 4680b1b..33c27d1 100644 --- a/src/Generators/Types/ExpandoObjectGenerator.cs +++ b/src/Generators/Types/ExpandoObjectGenerator.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using Soenneker.Reflection.Cache.Types; using Soenneker.Utils.AutoBogus.Context; -using Soenneker.Utils.AutoBogus.Extensions; using Soenneker.Utils.AutoBogus.Generators.Abstract; using Soenneker.Utils.AutoBogus.Services; @@ -24,11 +24,11 @@ object IAutoFakerGenerator.Generate(AutoFakerContext context) // Configure the context Type type = property.Value.GetType(); - context.Setup(context.GenerateType, type, property.Key); + context.Setup(context.GenerateType, CacheService.Cache.GetCachedType(type), property.Key); - var cachedType = CacheService.Cache.GetCachedType(type); + CachedType cachedType = CacheService.Cache.GetCachedType(type); - if (cachedType.IsExpandoObject()) + if (cachedType.IsExpandoObject) { context.Instance = property.Value; } @@ -38,7 +38,7 @@ object IAutoFakerGenerator.Generate(AutoFakerContext context) } // Generate the property values - IAutoFakerGenerator generator = GeneratorFactory.GetGenerator(context); + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.GetGenerator(context); target[property.Key] = generator.Generate(context); } diff --git a/src/Generators/Types/ListGenerator.cs b/src/Generators/Types/ListGenerator.cs index 1a7ce47..75fbf67 100644 --- a/src/Generators/Types/ListGenerator.cs +++ b/src/Generators/Types/ListGenerator.cs @@ -12,13 +12,20 @@ object IAutoFakerGenerator.Generate(AutoFakerContext context) { List list; - try + if (context.CachedType.IsInterface) { - list = (List)Activator.CreateInstance(context.GenerateType); + list = []; } - catch + else { - list = []; + try + { + list = context.CachedType.CreateInstance>(); + } + catch (Exception ex) + { + list = []; + } } List items = context.GenerateMany(); diff --git a/src/Generators/Types/ReadOnlyDictionaryGenerator.cs b/src/Generators/Types/ReadOnlyDictionaryGenerator.cs index 0a1ecbb..d96cdf1 100644 --- a/src/Generators/Types/ReadOnlyDictionaryGenerator.cs +++ b/src/Generators/Types/ReadOnlyDictionaryGenerator.cs @@ -19,6 +19,6 @@ object IAutoFakerGenerator.Generate(AutoFakerContext context) // Generate a standard dictionary and create the read only dictionary var items = generator.Generate(context) as IDictionary; - return Activator.CreateInstance(generateType, new[] { items }); + return Activator.CreateInstance(generateType, items); } } \ No newline at end of file diff --git a/src/Generators/Types/SetGenerator.cs b/src/Generators/Types/SetGenerator.cs index 2b93b40..ea925ce 100644 --- a/src/Generators/Types/SetGenerator.cs +++ b/src/Generators/Types/SetGenerator.cs @@ -6,20 +6,26 @@ namespace Soenneker.Utils.AutoBogus.Generators.Types; -internal sealed class SetGenerator - : IAutoFakerGenerator +internal sealed class SetGenerator : IAutoFakerGenerator { object IAutoFakerGenerator.Generate(AutoFakerContext context) { ISet set; - try + if (context.CachedType.IsInterface) { - set = (ISet)Activator.CreateInstance(context.GenerateType); + set = new HashSet(); } - catch + else { - set = new HashSet(); + try + { + set = (ISet)Activator.CreateInstance(context.GenerateType); + } + catch (Exception e) + { + set = new HashSet(); + } } List items = context.GenerateMany(); diff --git a/src/Generators/Types/TypeGenerator.cs b/src/Generators/Types/TypeGenerator.cs index 4529bfb..4baf2ca 100644 --- a/src/Generators/Types/TypeGenerator.cs +++ b/src/Generators/Types/TypeGenerator.cs @@ -1,5 +1,4 @@ -using System; -using Soenneker.Utils.AutoBogus.Context; +using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Generators.Abstract; namespace Soenneker.Utils.AutoBogus.Generators.Types; @@ -11,33 +10,10 @@ 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); + object instance = context.Binder.CreateInstance(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); + context.Binder.PopulateInstance(instance, context); return instance; } diff --git a/src/Generators/Types/ULongGenerator.cs b/src/Generators/Types/ULongGenerator.cs index c2ddc17..f0c5abf 100644 --- a/src/Generators/Types/ULongGenerator.cs +++ b/src/Generators/Types/ULongGenerator.cs @@ -3,8 +3,7 @@ namespace Soenneker.Utils.AutoBogus.Generators.Types; -internal sealed class ULongGenerator - : IAutoFakerGenerator +internal sealed class ULongGenerator: IAutoFakerGenerator { object IAutoFakerGenerator.Generate(AutoFakerContext context) { diff --git a/src/Override/AutoFakerOverride.cs b/src/Override/AutoFakerOverride.cs new file mode 100644 index 0000000..5f89fe0 --- /dev/null +++ b/src/Override/AutoFakerOverride.cs @@ -0,0 +1,39 @@ +using System; +using Bogus; +using Soenneker.Utils.AutoBogus.Context; +using Soenneker.Utils.AutoBogus.Generators; + +namespace Soenneker.Utils.AutoBogus.Override; + +public abstract class AutoFakerOverride : AutoFakerGeneratorOverride +{ + protected Faker Faker { get; private set; } + + protected Type Type { get; } + + private readonly bool _fakerSet; + + protected AutoFakerOverride(Faker? faker = null) + { + Type = typeof(T); + + if (faker == null) + return; + + Faker = faker; + _fakerSet = true; + } + + /// + /// Typically, SHOULD NOT be overriden again + /// + public override bool CanOverride(AutoFakerContext context) + { + bool shouldOverride = context.GenerateType == Type; + + if (shouldOverride && !_fakerSet) + Faker = context.Faker; + + return shouldOverride; + } +} \ No newline at end of file diff --git a/src/Services/AutoFakerBinderService.cs b/src/Services/AutoFakerBinderService.cs new file mode 100644 index 0000000..72bad8c --- /dev/null +++ b/src/Services/AutoFakerBinderService.cs @@ -0,0 +1,11 @@ +namespace Soenneker.Utils.AutoBogus.Services; + +internal static class AutoFakerBinderService +{ + internal static AutoFakerBinder Binder { get; private set; } = default!; + + internal static void SetBinder(AutoFakerBinder binder) + { + Binder = binder; + } +} \ No newline at end of file diff --git a/src/Services/DefaultConfigService.cs b/src/Services/DefaultConfigService.cs deleted file mode 100644 index 981e707..0000000 --- a/src/Services/DefaultConfigService.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Soenneker.Utils.AutoBogus.Config; -using System; - -namespace Soenneker.Utils.AutoBogus.Services; - -internal static class DefaultConfigService -{ - internal static AutoFakerConfig Config => _lazyDefaultConfig.Value; - - internal static readonly Lazy _lazyDefaultConfig = new(() => new(), true); -} \ No newline at end of file diff --git a/src/Services/GeneratorService.cs b/src/Services/GeneratorService.cs new file mode 100644 index 0000000..bcde8c7 --- /dev/null +++ b/src/Services/GeneratorService.cs @@ -0,0 +1,92 @@ +using Soenneker.Reflection.Cache.Types; +using Soenneker.Utils.AutoBogus.Generators.Abstract; +using Soenneker.Utils.AutoBogus.Generators.Types; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace Soenneker.Utils.AutoBogus.Services; + +internal static class GeneratorService +{ + private static readonly Lazy>> _cachedFundamentalGenerators = new(() => + { + var generatorMap = new Dictionary> + { + { typeof(string), new Lazy(() => new StringGenerator(), true) }, + { typeof(int), new Lazy(() => new IntGenerator(), true) }, + { typeof(bool), new Lazy(() => new BoolGenerator(), true) }, + { typeof(double), new Lazy(() => new DoubleGenerator(), true) }, + { typeof(DateTime), new Lazy(() => new DateTimeGenerator(), true) }, + { typeof(byte), new Lazy(() => new ByteGenerator(), true) }, + { typeof(char), new Lazy(() => new CharGenerator(), true) }, + { typeof(decimal), new Lazy(() => new DecimalGenerator(), true) }, + { typeof(float), new Lazy(() => new FloatGenerator(), true) }, + { typeof(long), new Lazy(() => new LongGenerator(), true) }, + { typeof(Guid), new Lazy(() => new GuidGenerator(), true) }, + { typeof(sbyte), new Lazy(() => new SByteGenerator(), true) }, + { typeof(short), new Lazy(() => new ShortGenerator(), true) }, + { typeof(uint), new Lazy(() => new UIntGenerator(), true) }, + { typeof(ulong), new Lazy(() => new ULongGenerator(), true) }, + { typeof(Uri), new Lazy(() => new UriGenerator(), true) }, + { typeof(ushort), new Lazy(() => new UShortGenerator(), true) }, + { typeof(DateTimeOffset), new Lazy(() => new DateTimeOffsetGenerator(), true) }, + { typeof(DateOnly), new Lazy(() => new DateOnlyGenerator(), true) }, + { typeof(TimeOnly), new Lazy(() => new TimeOnlyGenerator(), true) }, + { typeof(IPAddress), new Lazy(() => new IpAddressGenerator(), true) }, + }; + + return generatorMap; + }); + private static readonly Lazy>> _cachedFundamentalGeneratorsByInt = new(() => + { + Dictionary> hashCodesMap = _cachedFundamentalGenerators.Value.ToDictionary( + kvp => kvp.Key.GetHashCode(), + kvp => kvp.Value + ); + + return hashCodesMap; + }, true); + + private static readonly ConcurrentDictionary _cachedGenerators = []; + + public static IAutoFakerGenerator? GetFundamentalGenerator(CachedType cachedType) + { + int hashCode = cachedType.CacheKey.Value; + + IAutoFakerGenerator? result = _cachedFundamentalGeneratorsByInt.Value.GetValueOrDefault(hashCode)?.Value; + return result; + } + + public static IAutoFakerGenerator? GetGenerator(CachedType cachedType) + { + int hashCode = cachedType.CacheKey.Value; + + IAutoFakerGenerator? result = _cachedGenerators.GetValueOrDefault(hashCode); + + return result; + } + + public static void SetGenerator(CachedType cachedType, IAutoFakerGenerator generator) + { + int hashCode = cachedType.CacheKey.Value; + + _cachedGenerators.TryAdd(hashCode, generator); + } + + /// + /// For test only! + /// + /// + public static List GetSupportedFundamentalTypes() + { + return _cachedFundamentalGenerators.Value.Select(c => c.Key).ToList(); + } + + public static void Clear() + { + _cachedGenerators.Clear(); + } +} \ No newline at end of file diff --git a/src/Soenneker.Utils.AutoBogus.csproj b/src/Soenneker.Utils.AutoBogus.csproj index b7855ef..0d48d42 100644 --- a/src/Soenneker.Utils.AutoBogus.csproj +++ b/src/Soenneker.Utils.AutoBogus.csproj @@ -27,7 +27,7 @@ https://github.com/soenneker/soenneker.utils.autobogus false true - latest + preview README.md icon.png @@ -42,7 +42,7 @@ - + diff --git a/test/Soenneker.Utils.AutoBogus.Console/Program.cs b/test/Soenneker.Utils.AutoBogus.Console/Program.cs index fc02373..471dc41 100644 --- a/test/Soenneker.Utils.AutoBogus.Console/Program.cs +++ b/test/Soenneker.Utils.AutoBogus.Console/Program.cs @@ -1,4 +1,5 @@ using Soenneker.Utils.AutoBogus.Abstract; +using Soenneker.Utils.AutoBogus.Tests.Dtos.Complex; namespace Soenneker.Utils.AutoBogus.Tests.Console; @@ -6,11 +7,11 @@ public class Program { public static void Main(string[] args) { - IAutoFaker? faker = AutoFaker.Create(); + IAutoFaker faker = new AutoFaker(); for (int i = 0; i < 10000; i++) { - var order = faker.Generate(); + var order = faker.Generate(); } } } \ No newline at end of file diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoConfigBuilderFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoConfigBuilderFixture.cs index bcd85b9..04ee8ec 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoConfigBuilderFixture.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoConfigBuilderFixture.cs @@ -18,9 +18,10 @@ private interface ITestBuilder { } public AutoConfigBuilderFixture() { + var autoFaker = new AutoFaker(); _faker = new Faker(); _fakerConfig = new AutoFakerConfig(); - _builder = new AutoFakerConfigBuilder(_fakerConfig); + _builder = new AutoFakerConfigBuilder(_fakerConfig, autoFaker); } public class WithLocale @@ -35,47 +36,37 @@ public void Should_Set_Config_Locale() _fakerConfig.Locale.Should().Be(locale); } - - [Fact] - public void Should_Set_Config_Locale_To_Default_If_Null() - { - _fakerConfig.Locale = _faker.Random.String(); - - _builder.WithLocale(null, null); - - _fakerConfig.Locale.Should().Be(AutoFakerConfig.DefaultLocale); - } } public class WithDateTimeKind : AutoConfigBuilderFixture { - [Fact] - public void Should_Set_Config_DateTimeKind() - { - var kind = DateTimeKind.Utc; - _builder.WithDateTimeKind(context => kind, null); - _fakerConfig.DateTimeKind.Invoke(null).Should().Be(kind); - } - - [Fact] - public void Should_Set_Config_DateTimeKind_To_Default_If_Null() - { - var kind = AutoFakerConfig.DefaultDateTimeKind.Invoke(null); - _builder.WithDateTimeKind(null, null); - _fakerConfig.DateTimeKind.Invoke(null).Should().Be(kind); - } + //[Fact] + //public void Should_Set_Config_DateTimeKind() + //{ + // var kind = DateTimeKind.Utc; + // _builder.WithDateTimeKind(context => kind, null); + // _fakerConfig.DateTimeKind.Invoke(null).Should().Be(kind); + //} + + //[Fact] + //public void Should_Set_Config_DateTimeKind_To_Default_If_Null() + //{ + // var kind = AutoFakerConfig.DefaultDateTimeKind.Invoke(null); + // _builder.WithDateTimeKind(null, null); + // _fakerConfig.DateTimeKind.Invoke(null).Should().Be(kind); + //} private sealed record Obj(DateTime Birthday); - [Fact] - public void Should_ConvertToUtc() - { - var obj = AutoFaker.Generate(builder => - { - builder.WithDateTimeKind(DateTimeKind.Utc); - }); - obj.Birthday.Should().Be(obj.Birthday.ToUniversalTime()); - } + //[Fact] + //public void Should_ConvertToUtc() + //{ + // var obj = AutoFaker.Generate(builder => + // { + // builder.WithDateTimeKind(DateTimeKind.Utc); + // }); + // obj.Birthday.Should().Be(obj.Birthday.ToUniversalTime()); + //} [Fact] public void Should_BeLocal() @@ -93,19 +84,9 @@ public void Should_Set_Config_RepeatCount() { int count = _faker.Random.Int(); - _builder.WithRepeatCount(context => count, null); + _builder.WithRepeatCount(count, null); - _fakerConfig.RepeatCount.Invoke(null).Should().Be(count); - } - - [Fact] - public void Should_Set_Config_RepeatCount_To_Default_If_Null() - { - int count = AutoFakerConfig.DefaultRepeatCount.Invoke(null); - - _builder.WithRepeatCount(null, null); - - _fakerConfig.RepeatCount.Invoke(null).Should().Be(count); + _fakerConfig.RepeatCount.Should().Be(count); } } @@ -117,19 +98,9 @@ public void Should_Set_Config_RecursiveDepth() { int depth = _faker.Random.Int(); - _builder.WithRecursiveDepth(context => depth, null); - - _fakerConfig.RecursiveDepth.Invoke(null).Should().Be(depth); - } - - [Fact] - public void Should_Set_Config_RecursiveDepth_To_Default_If_Null() - { - int depth = AutoFakerConfig.DefaultRecursiveDepth.Invoke(null); + _builder.WithRecursiveDepth( depth, null); - _builder.WithRecursiveDepth(null, null); - - _fakerConfig.RecursiveDepth.Invoke(null).Should().Be(depth); + _fakerConfig.RecursiveDepth.Should().Be(depth); } } @@ -142,32 +113,19 @@ public void Should_Set_Config_TreeDepth() { int depth = _faker.Random.Int(); - _builder.WithTreeDepth(context => depth, null); + _builder.WithTreeDepth(depth, null); - _fakerConfig.TreeDepth.Invoke(null).Should().Be(depth); + _fakerConfig.TreeDepth.Should().Be(depth); } [Fact] public void Should_Set_Config_TreeDepth_To_Default_If_Null() { - int? depth = AutoFakerConfig.DefaultTreeDepth.Invoke(null); + int? depth = AutoFakerDefaultConfigOptions.DefaultTreeDepth; _builder.WithTreeDepth(null, null); - _fakerConfig.TreeDepth.Invoke(null).Should().Be(depth); - } - } - - public class WithFakerHub - : AutoConfigBuilderFixture - { - [Fact] - public void Should_Set_Config_FakerHub() - { - var faker = new Faker(); - - _builder.WithFaker(faker, null); - _builder.FakerConfig.Faker.Should().Be(faker); + _fakerConfig.TreeDepth.Should().Be(depth); } } @@ -177,10 +135,13 @@ public class WithSkip_Type [Fact] public void Should_Not_Add_Type_If_Already_Added() { - Type? type1 = typeof(int); - Type? type2 = typeof(int); + Type type1 = typeof(int); + Type type2 = typeof(int); - _fakerConfig.SkipTypes.Add(type1); + _fakerConfig.SkipTypes = + [ + type1 + ]; _builder.WithSkip(type2, null); @@ -190,10 +151,13 @@ public void Should_Not_Add_Type_If_Already_Added() [Fact] public void Should_Add_Type_To_Skip() { - Type? type1 = typeof(int); - Type? type2 = typeof(string); + Type type1 = typeof(int); + Type type2 = typeof(string); - _fakerConfig.SkipTypes.Add(type1); + _fakerConfig.SkipTypes = + [ + type1 + ]; _builder.WithSkip(type2, null); @@ -216,10 +180,13 @@ private sealed class TestSkip [Fact] public void Should_Not_Add_Member_If_Already_Added() { - Type? type = typeof(TestSkip); + Type type = typeof(TestSkip); var member = $"{type.FullName}.Value"; - _fakerConfig.SkipPaths.Add(member); + _fakerConfig.SkipPaths = + [ + member + ]; _builder.WithSkip(type, "Value", null); @@ -229,11 +196,13 @@ public void Should_Not_Add_Member_If_Already_Added() [Fact] public void Should_Add_MemberName_To_Skip() { - Type? type = typeof(TestSkip); + Type type = typeof(TestSkip); string? path = _faker.Random.String(); - _fakerConfig.SkipPaths.Add(path); - + _fakerConfig.SkipPaths = + [ + path + ]; _builder.WithSkip(type, "Value", null); _fakerConfig.SkipPaths.Should().BeEquivalentTo(new[] @@ -255,10 +224,12 @@ private sealed class TestSkip [Fact] public void Should_Not_Add_Member_If_Already_Added() { - Type? type = typeof(TestSkip); + Type type = typeof(TestSkip); var member = $"{type.FullName}.Value"; - - _fakerConfig.SkipPaths.Add(member); + _fakerConfig.SkipPaths = + [ + member + ]; _builder.WithSkip("Value", null); @@ -268,10 +239,13 @@ public void Should_Not_Add_Member_If_Already_Added() [Fact] public void Should_Add_MemberName_To_Skip() { - Type? type = typeof(TestSkip); + Type type = typeof(TestSkip); string? path = _faker.Random.String(); - _fakerConfig.SkipPaths.Add(path); + _fakerConfig.SkipPaths = + [ + path + ]; _builder.WithSkip("Value", null); @@ -286,15 +260,15 @@ public void Should_Add_MemberName_To_Skip() public class WithOverride : AutoConfigBuilderFixture { - private class TestGeneratorOverride - : GeneratorOverride + private class TestAutoFakerGeneratorOverride + : AutoFakerGeneratorOverride { public override bool CanOverride(AutoFakerContext context) { return false; } - public override void Generate(AutoFakerContextOverride context) + public override void Generate(AutoFakerOverrideContext context) { } } @@ -303,14 +277,18 @@ public void Should_Not_Add_Null_Override() { _builder.WithOverride(null, null); - _fakerConfig.Overrides.Should().BeEmpty(); + _fakerConfig.Overrides.Should().BeNull(); } [Fact] public void Should_Not_Add_Override_If_Already_Added() { - var generatorOverride = new TestGeneratorOverride(); - _fakerConfig.Overrides.Add(generatorOverride); + var generatorOverride = new TestAutoFakerGeneratorOverride(); + + _fakerConfig.Overrides = + [ + generatorOverride + ]; _builder.WithOverride(generatorOverride, null); @@ -320,10 +298,13 @@ public void Should_Not_Add_Override_If_Already_Added() [Fact] public void Should_Add_Override_If_Equivalency_Is_Different() { - var generatorOverride1 = new TestGeneratorOverride(); - var generatorOverride2 = new TestGeneratorOverride(); + var generatorOverride1 = new TestAutoFakerGeneratorOverride(); + var generatorOverride2 = new TestAutoFakerGeneratorOverride(); - _fakerConfig.Overrides.Add(generatorOverride1); + _fakerConfig.Overrides = + [ + generatorOverride1 + ]; _builder.WithOverride(generatorOverride2, null); diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerFixture.cs index 5597827..5630a8c 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerFixture.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerFixture.cs @@ -3,12 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Bogus; using FluentAssertions; using Soenneker.Utils.AutoBogus.Abstract; using Soenneker.Utils.AutoBogus.Config; using Soenneker.Utils.AutoBogus.Config.Abstract; -using Soenneker.Utils.AutoBogus.Generators; using Soenneker.Utils.AutoBogus.Services; using Soenneker.Utils.AutoBogus.Tests.Dtos; using Soenneker.Utils.AutoBogus.Tests.Dtos.Complex; @@ -19,10 +17,6 @@ namespace Soenneker.Utils.AutoBogus.Tests; public class AutoFakerFixture { - private class TestFakerBinder - : AutoFakerBinder - { } - private const string _name = "Generate"; private static readonly Type _type = typeof(AutoFaker); @@ -32,14 +26,17 @@ public class Configure [Fact] public void Should_Configure_Default_Config() { - AutoFakerConfig fakerConfig = null; - AutoFaker.Configure(builder => + AutoFakerConfig? fakerConfig = null; + + var autoFaker = new AutoFaker(); + + autoFaker.Configure(builder => { var instance = builder as AutoFakerConfigBuilder; - fakerConfig = instance.FakerConfig; + fakerConfig = instance._autoFakerConfig; }); - fakerConfig.Should().Be(DefaultConfigService.Config); + fakerConfig.Should().Be(autoFaker.Config); } } @@ -49,8 +46,10 @@ public class Create [Fact] public void Should_Configure_Child_Config() { - Action? configure = CreateConfigure(DefaultConfigService.Config); - AutoFaker.Create(configure).Should().BeOfType(); + Action configure = CreateConfigure(new AutoFakerConfig()); + + var autoFaker = new AutoFaker(configure); + autoFaker.Should().BeOfType(); } } @@ -62,31 +61,31 @@ public class Generate_Instance private static MethodInfo _generate = _type.GetMethod(_methodName, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Action) }, null); private static MethodInfo _generateMany = _type.GetMethod(_methodName, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(int), typeof(Action) }, null); - private IAutoFaker _faker; - private AutoFakerConfig _fakerConfig; + private readonly IAutoFaker _faker; + private readonly AutoFakerConfig _fakerConfig; public Generate_Instance() { - var faker = AutoFaker.Create() as AutoFaker; + var faker = new AutoFaker(); _faker = faker; - _fakerConfig = faker.FakerConfig; + _fakerConfig = new AutoFakerConfig(); } [Theory] [MemberData(nameof(GetTypes))] public void Should_Generate_Type(Type type) { - Action? configure = CreateConfigure(_fakerConfig); + Action configure = CreateConfigure(_fakerConfig); AssertGenerate(type, _generate, _faker, configure); } [Theory] [MemberData(nameof(GetTypes))] public void Should_Generate_Many_Types(Type type) - { - int count = AutoFakerConfig.DefaultRepeatCount.Invoke(null); - Action? configure = CreateConfigure(_fakerConfig); + { + int count = AutoFakerDefaultConfigOptions.DefaultRepeatCount; + Action configure = CreateConfigure(_fakerConfig); AssertGenerateMany(type, _generateMany, _faker, count, configure); } @@ -95,34 +94,22 @@ public void Should_Generate_Many_Types(Type type) public void Should_Generate_Complex_Type() { Action configure = CreateConfigure(_fakerConfig); - _faker.Generate(configure).Should().BeGeneratedWithoutMocks(); + var generatedOrder = _faker.Generate(configure); + + generatedOrder.Should().BeGeneratedWithoutMocks(); } [Fact] public void Should_Generate_Many_Complex_Types() { - int count = AutoFakerConfig.DefaultRepeatCount.Invoke(null); - Action? configure = CreateConfigure(_fakerConfig); - List? instances = _faker.Generate(count, configure); + int count = AutoFakerDefaultConfigOptions.DefaultRepeatCount; + Action configure = CreateConfigure(_fakerConfig); + List instances = _faker.Generate(count, configure); AssertGenerateMany(instances); } } - public class Generate_Instance_Faker : AutoFakerFixture - { - private readonly IAutoFaker _faker; - private AutoFakerConfig _fakerConfig; - - public Generate_Instance_Faker() - { - var faker = AutoFaker.Create() as AutoFaker; - - _faker = faker; - _fakerConfig = faker.FakerConfig; - } - } - public class Generate_Static : AutoFakerFixture { @@ -133,7 +120,7 @@ public class Generate_Static [MemberData(nameof(GetTypes))] public void Should_Generate_Type(Type type) { - Action? configure = CreateConfigure(DefaultConfigService.Config); + Action configure = CreateConfigure(new AutoFakerConfig()); AssertGenerate(type, _generate, null, configure); } @@ -141,8 +128,8 @@ public void Should_Generate_Type(Type type) [MemberData(nameof(GetTypes))] public void Should_Generate_Many_Types(Type type) { - int count = AutoFakerConfig.DefaultRepeatCount.Invoke(null); - Action? configure = CreateConfigure(DefaultConfigService.Config); + int count = AutoFakerDefaultConfigOptions.DefaultRepeatCount; + Action configure = CreateConfigure(new AutoFakerConfig()); AssertGenerateMany(type, _generateMany, null, count, configure); } @@ -150,52 +137,52 @@ public void Should_Generate_Many_Types(Type type) [Fact] public void Should_Generate_Complex_Type() { - Action? configure = CreateConfigure(DefaultConfigService.Config); + Action configure = CreateConfigure(new AutoFakerConfig()); AutoFaker.Generate(configure).Should().BeGeneratedWithoutMocks(); } [Fact] public void Should_Generate_Many_Complex_Types() { - int count = AutoFakerConfig.DefaultRepeatCount.Invoke(null); - Action? configure = CreateConfigure(DefaultConfigService.Config); - List? instances = AutoFaker.Generate(count, configure); + int count = AutoFakerDefaultConfigOptions.DefaultRepeatCount; + Action configure = CreateConfigure(new AutoFakerConfig()); + List instances = AutoFaker.Generate(count, configure); AssertGenerateMany(instances); } } - public class AutoFaker_WithFakerHub : AutoFakerFixture - { - [Fact] - public void Should_Use_Caller_Supplied_Faker() - { - // We infer that our FakerHub was used by reseeding it and testing that we get the same sequence both times. - var faker = new Faker(); + //public class AutoFaker_WithFakerHub : AutoFakerFixture + //{ + // [Fact] + // public void Should_Use_Caller_Supplied_Faker() + // { + // // We infer that our FakerHub was used by reseeding it and testing that we get the same sequence both times. + // var faker = new Faker(); - Action configure = CreateConfigure( - DefaultConfigService.Config, - builder => builder.WithFaker(faker)); + // Action configure = CreateConfigure( + // new AutoFakerConfig(), + // builder => builder.WithFaker(faker)); - IAutoFaker autoFaker = AutoFaker.Create(configure); + // IAutoFaker autoFaker = AutoFaker.Create(configure); - faker.Random = new Randomizer(1); + // faker.Random = new Randomizer(1); - var instance1 = autoFaker.Generate(); + // var instance1 = autoFaker.Generate(); - faker.Random = new Randomizer(1); + // faker.Random = new Randomizer(1); - var instance2 = autoFaker.Generate(); + // var instance2 = autoFaker.Generate(); - instance1.Should().BeEquivalentTo(instance2); - } + // instance1.Should().BeEquivalentTo(instance2); + // } - class TestObject - { - public int IntegerValue; - public string StringValue; - } - } + // class TestObject + // { + // public int IntegerValue; + // public string StringValue; + // } + //} public class Behaviors_Skip : AutoFakerFixture { @@ -247,7 +234,7 @@ public void Should_Not_Generate_Abstract_Class_Type() public class Behaviors_Recursive : AutoFakerFixture { - private TestRecursiveClass _instance; + private readonly TestRecursiveClass _instance; public Behaviors_Recursive() { @@ -269,10 +256,10 @@ public void Should_Generate_Recursive_Types() [Fact] public void Should_Generate_Recursive_Lists() { - IEnumerable? children = _instance.Children; - List? children1 = children.SelectMany(c => c.Children).ToList(); - List? children2 = children1.SelectMany(c => c.Children).ToList(); - List? children3 = children2.Where(c => c.Children != null).ToList(); + IEnumerable children = _instance.Children; + List children1 = children.SelectMany(c => c.Children).ToList(); + List children2 = children1.SelectMany(c => c.Children).ToList(); + List children3 = children2.Where(c => c.Children != null).ToList(); children.Should().HaveCount(3); children1.Should().HaveCount(9); @@ -292,7 +279,7 @@ public void Should_Generate_Recursive_Sub_Types() public static IEnumerable GetTypes() { - foreach (Type? type in GeneratorFactory.Generators.Keys) + foreach (Type? type in GeneratorService.GetSupportedFundamentalTypes()) { yield return new object[] { type }; } @@ -304,23 +291,20 @@ public static IEnumerable GetTypes() yield return new object[] { typeof(int?) }; } - private Action CreateConfigure(AutoFakerConfig assertFakerConfig, Action configure = null) + private static Action CreateConfigure(AutoFakerConfig assertFakerConfig, Action? configure = null) { return builder => { - if (configure != null) - { - configure.Invoke(builder); - } + configure?.Invoke(builder); var instance = builder as AutoFakerConfigBuilder; - instance.FakerConfig.Should().NotBe(assertFakerConfig); + instance._autoFakerConfig.Should().NotBe(assertFakerConfig); }; } public static void AssertGenerate(Type type, MethodInfo methodInfo, IAutoFaker faker, params object[] args) { - MethodInfo? method = methodInfo.MakeGenericMethod(type); + MethodInfo method = methodInfo.MakeGenericMethod(type); object? instance = method.Invoke(faker, args); instance.Should().BeGenerated(); @@ -328,8 +312,8 @@ public static void AssertGenerate(Type type, MethodInfo methodInfo, IAutoFaker f public static void AssertGenerateMany(Type type, MethodInfo methodInfo, IAutoFaker faker, params object[] args) { - int count = AutoFakerConfig.DefaultRepeatCount.Invoke(null); - MethodInfo? method = methodInfo.MakeGenericMethod(type); + int count = AutoFakerDefaultConfigOptions.DefaultRepeatCount; + MethodInfo method = methodInfo.MakeGenericMethod(type); var instances = method.Invoke(faker, args) as ICollection; instances.Count.Should().Be(count); @@ -342,7 +326,7 @@ public static void AssertGenerateMany(Type type, MethodInfo methodInfo, IAutoFak public static void AssertGenerateMany(IEnumerable instances) { - int count = AutoFakerConfig.DefaultRepeatCount.Invoke(null); + int count = AutoFakerDefaultConfigOptions.DefaultRepeatCount; instances.Should().HaveCount(count); diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs index fa0e33f..8aca0aa 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs @@ -1,6 +1,9 @@ using FluentAssertions; using Soenneker.Utils.AutoBogus.Abstract; using Soenneker.Utils.AutoBogus.Tests.Dtos.Complex; +using System.Collections.Generic; +using System.Diagnostics; +using Soenneker.Utils.AutoBogus.Tests.Dtos.Simple; using Xunit; namespace Soenneker.Utils.AutoBogus.Tests; @@ -10,16 +13,38 @@ public class AutoFakerTests [Fact] public void Generate_order_should_generate() { - IAutoFaker faker = AutoFaker.Create(); + IAutoFaker faker = new AutoFaker(); var order = faker.Generate(); order.Should().NotBeNull(); } + + [Fact] + public void Generate_dictionary_should_generate() + { + IAutoFaker faker = new AutoFaker(); + + var dictionary = faker.Generate>(); + dictionary.Should().NotBeNull(); + } + + [Fact] + public void Generate_struct_should_generate() + { + IAutoFaker faker = new AutoFaker(); + + var structObj = faker.Generate(); + structObj.Should().NotBeNull(); + + // product.Reviews.Count.Should().BeGreaterThan(0); + // product. + } + [Fact] public void Generate_Product_should_generate() { - IAutoFaker faker = AutoFaker.Create(); + IAutoFaker faker = new AutoFaker(); var product = faker.Generate(); product.Should().NotBeNull(); @@ -29,13 +54,33 @@ public void Generate_Product_should_generate() } [Fact] - public void Generate_many_should_generate() + public void Generate_many_Orders_should_generate() { - IAutoFaker faker = AutoFaker.Create(); + IAutoFaker faker = new AutoFaker(); + + Stopwatch stopwatch = Stopwatch.StartNew(); for (var i = 0; i < 1000; i++) { var order = faker.Generate(); } + + stopwatch.Stop(); + } + + [Fact] + public void Generate_many_int_should_generate() + { + IAutoFaker faker = new AutoFaker(); + + List intList = new List(); + + for (var i = 0; i < 1000; i++) + { + var generated = faker.Generate(); + intList.Add(generated); + } + + intList.Count.Should().Be(1000); } } \ No newline at end of file diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoGenerateContextFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoGenerateContextFixture.cs index 4dac86e..acd47e6 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoGenerateContextFixture.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoGenerateContextFixture.cs @@ -21,6 +21,8 @@ public AutoGenerateContextFixture() _faker = new Faker(); _ruleSets = new List(); _fakerConfig = new AutoFakerConfig(); + + //ConfigService.SetCustomConfig(_fakerConfig); } public class GenerateMany_Internal @@ -33,7 +35,7 @@ public GenerateMany_Internal() { _value = _faker.Random.Int(); _items = new List { _value }; - _context = new AutoFakerContext(_fakerConfig) + _context = new AutoFakerContext(_fakerConfig, new Faker(), new AutoFakerBinder(_fakerConfig)) { RuleSets = _ruleSets }; @@ -43,9 +45,9 @@ public GenerateMany_Internal() public void Should_Generate_Configured_RepeatCount() { int count = _faker.Random.Int(3, 5); - List? expected = Enumerable.Range(0, count).Select(i => _value).ToList(); + List expected = Enumerable.Range(0, count).Select(i => _value).ToList(); - _fakerConfig.RepeatCount = context => count; + _fakerConfig.RepeatCount = count; AutoGenerateContextExtension.GenerateMany(_context, null, _items, false, 1, () => _value); @@ -82,13 +84,13 @@ public void Should_Short_Circuit_If_Unique_Attempts_Overflow() { var attempts = 0; - AutoGenerateContextExtension.GenerateMany(_context, 2, _items, true, 1, () => + AutoGenerateContextExtension.GenerateMany(_context, 2, _items, true, AutoFakerDefaultConfigOptions.GenerateAttemptsThreshold, () => { attempts++; return _value; }); - attempts.Should().Be(AutoFakerConfig.GenerateAttemptsThreshold); + attempts.Should().Be(AutoFakerDefaultConfigOptions.GenerateAttemptsThreshold + 1); _items.Should().BeEquivalentTo(new[] { _value }); } diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorOverridesFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorOverridesFixture.cs index f5ef008..2b5c098 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorOverridesFixture.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorOverridesFixture.cs @@ -10,23 +10,23 @@ namespace Soenneker.Utils.AutoBogus.Tests; public class AutoGeneratorOverridesFixture { private sealed class TestOverride - : GeneratorOverride + : AutoFakerGeneratorOverride { - public TestOverride(bool preinitialize, Action generator) + public TestOverride(bool preinitialize, Action generator) { Preinitialize = preinitialize; Generator = generator; } public override bool Preinitialize { get; } - private Action Generator { get; } + private Action Generator { get; } public override bool CanOverride(AutoFakerContext context) { return context.GenerateType == typeof(OverrideClass); } - public override void Generate(AutoFakerContextOverride context) + public override void Generate(AutoFakerOverrideContext context) { Generator.Invoke(context); } diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.Data.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.Data.cs index 1336b85..7b8a2e1 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.Data.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.Data.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Reflection; using FluentAssertions; +using Soenneker.Reflection.Cache.Types; using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Generators.Types; using Soenneker.Utils.AutoBogus.Services; @@ -28,7 +29,7 @@ public static IEnumerable GetTryCreateGeneratorTestCases() [MemberData(nameof(GetTryCreateGeneratorTestCases))] public void TryCreateGenerator_Should_Create_Generator(Type dataSetType, bool shouldSucceed) { - var cachedType = CacheService.Cache.GetCachedType(dataSetType); + CachedType cachedType = CacheService.Cache.GetCachedType(dataSetType); // Act bool success = DataSetGenerator.TryCreateGenerator(cachedType, out DataSetGenerator? generator); @@ -56,16 +57,16 @@ public static IEnumerable GetGenerateTestCases() public void Generate_Should_Return_DataSet(Type dataSetType) { // Arrange - AutoFakerContext? context = CreateContext(dataSetType); + AutoFakerContext context = CreateContext(dataSetType); - var cachedType = CacheService.Cache.GetCachedType(context.GenerateType); + CachedType cachedType = CacheService.Cache.GetCachedType(context.GenerateType); bool success = DataSetGenerator.TryCreateGenerator(cachedType, out DataSetGenerator? generator); Skip.IfNot(success, $"couldn't create generator for {dataSetType.Name}"); // Act - object? result = generator.Generate(context); + object result = generator.Generate(context); // Assert result.Should().BeOfType(dataSetType); @@ -88,37 +89,37 @@ public void Generate_Should_Return_DataSet_With_Specified_DataTable_Row_Counts(T // Arrange var rowCountByTable = new Dictionary(); - Func rowCountFunctor = - (AutoFakerContext ctx) => - { - var dataTable = (DataTable)ctx.Instance; + //Func rowCountFunctor = + // (AutoFakerContext ctx) => + // { + // var dataTable = (DataTable)ctx.Instance; - if (!rowCountByTable.TryGetValue(dataTable, out int count)) - { - // Because Table2.RecordID is a Primary Key and this Unique, Table2 - // must not have more records than Table1 otherwise it is impossible - // to have unique values. So, assuming that the dependent tables - // come last in the DataSet, we have a decreasing count as we progress - // through the list. + // if (!rowCountByTable.TryGetValue(dataTable, out int count)) + // { + // // Because Table2.RecordID is a Primary Key and this Unique, Table2 + // // must not have more records than Table1 otherwise it is impossible + // // to have unique values. So, assuming that the dependent tables + // // come last in the DataSet, we have a decreasing count as we progress + // // through the list. - count = 100 - (rowCountByTable.Count + 1) * 10; + // count = 100 - (rowCountByTable.Count + 1) * 10; - rowCountByTable[dataTable] = count; - } + // rowCountByTable[dataTable] = count; + // } - return count; - }; + // return count; + // }; - AutoFakerContext? context = CreateContext(dataSetType, dataTableRowCountFunctor: rowCountFunctor); + AutoFakerContext context = CreateContext(dataSetType, dataTableRowCountFunctor: 3); - var cachedType = CacheService.Cache.GetCachedType(context.GenerateType); + CachedType cachedType = CacheService.Cache.GetCachedType(context.GenerateType); bool success = DataSetGenerator.TryCreateGenerator(cachedType, out DataSetGenerator? generator); Skip.IfNot(success, $"couldn't create generator for {dataSetType.Name}"); // Act - object? result = generator.Generate(context); + object result = generator.Generate(context); // Assert result.Should().BeOfType(dataSetType); @@ -131,57 +132,10 @@ public void Generate_Should_Return_DataSet_With_Specified_DataTable_Row_Counts(T { table.Columns.Should().NotBeEmpty(); - table.Rows.Should().HaveCount(rowCountByTable[table]); + table.Rows.Should().HaveCount(3); } } - [SkippableFact] - public void Generate_Should_Fail_If_Requested_Row_Count_Is_Impossible_Due_To_Foreign_Key_Constraint() - { - // Arrange - Type? dataSetType = typeof(TypedDataSetWithRelations); - - var rowCountByTable = new Dictionary(); - - Func rowCountFunctor = - (AutoFakerContext ctx) => - { - var dataTable = (DataTable)ctx.Instance; - - if (!rowCountByTable.TryGetValue(dataTable, out int count)) - { - // Because Table2.RecordID is a Primary Key and this Unique, Table2 - // must not have more records than Table1 otherwise it is impossible - // to have unique values. So, assuming that the dependent tables - // come last in the DataSet, having an increasing count creates an - // impossible situation where there aren't enough related records - // to produce unique values. - - count = 100 + (rowCountByTable.Count + 1) * 10; - - rowCountByTable[dataTable] = count; - } - - return count; - }; - - AutoFakerContext? context = CreateContext(dataSetType, dataTableRowCountFunctor: rowCountFunctor); - - var cachedType = CacheService.Cache.GetCachedType(context.GenerateType); - - bool success = DataSetGenerator.TryCreateGenerator(cachedType, out DataSetGenerator? generator); - - Skip.IfNot(success, $"couldn't create generator for {dataSetType.Name}"); - - // Act - Action action = - () => generator.Generate(context); - - // Assert - action.Should().Throw() - .Which.Message.Should().StartWith("Unable to satisfy the requested row count"); - } - internal class TypedDataSet : DataSet { public TypedDataSet() @@ -239,7 +193,7 @@ public static IEnumerable GetTryCreateGeneratorTestCases() [MemberData(nameof(GetTryCreateGeneratorTestCases))] public void TryCreateGenerator_Should_Create_Generator(Type dataTableType, bool shouldSucceed) { - var cachedType = CacheService.Cache.GetCachedType(dataTableType); + CachedType cachedType = CacheService.Cache.GetCachedType(dataTableType); // Act bool success = DataTableGenerator.TryCreateGenerator(cachedType, out DataTableGenerator? generator); @@ -266,16 +220,16 @@ public static IEnumerable GetGenerateTestCases() public void Generate_Should_Return_DataTable(Type dataTableType) { // Arrange - AutoFakerContext? context = CreateContext(dataTableType); + AutoFakerContext context = CreateContext(dataTableType); - var cachedType = CacheService.Cache.GetCachedType(context.GenerateType); + CachedType cachedType = CacheService.Cache.GetCachedType(context.GenerateType); bool success = DataTableGenerator.TryCreateGenerator(cachedType, out DataTableGenerator? generator); Skip.IfNot(success, $"couldn't create generator for {dataTableType.Name}"); // Act - object? result = generator.Generate(context); + object result = generator.Generate(context); // Assert result.Should().BeOfType(dataTableType); @@ -291,21 +245,19 @@ public void Generate_Should_Return_DataTable(Type dataTableType) public void Generate_Should_Return_DataTable_With_Specified_Row_Count(Type dataTableType) { // Arrange - const int RowCount = 100; + const int RowCount = 3; - Func rowCountFunctor = - _ => RowCount; - AutoFakerContext? context = CreateContext(dataTableType, dataTableRowCountFunctor: rowCountFunctor); + AutoFakerContext context = CreateContext(dataTableType, dataTableRowCountFunctor: 3); - var cachedType = CacheService.Cache.GetCachedType(context.GenerateType); + CachedType cachedType = CacheService.Cache.GetCachedType(context.GenerateType); bool success = DataTableGenerator.TryCreateGenerator(cachedType, out DataTableGenerator? generator); Skip.IfNot(success, $"couldn't create generator for {dataTableType.Name}"); // Act - object? result = generator.Generate(context); + object result = generator.Generate(context); // Assert result.Should().BeOfType(dataTableType); diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.ReadOnlyDictionary.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.ReadOnlyDictionary.cs index 3ad1506..b797126 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.ReadOnlyDictionary.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.ReadOnlyDictionary.cs @@ -22,17 +22,17 @@ public class ReadOnlyDictionaryGenerator [InlineData(typeof(ReadOnlyDictionary))] public void Generate_Should_Return_Dictionary(Type type) { - Type[]? genericTypes = type.GetGenericArguments(); - Type? keyType = genericTypes.ElementAt(0); - Type? valueType = genericTypes.ElementAt(1); - IAutoFakerGenerator? generator = CreateGenerator(typeof(ReadOnlyDictionaryGenerator<,>), keyType, valueType); + Type[] genericTypes = type.GetGenericArguments(); + Type keyType = genericTypes.ElementAt(0); + Type valueType = genericTypes.ElementAt(1); + IAutoFakerGenerator generator = CreateGenerator(typeof(ReadOnlyDictionaryGenerator<,>), keyType, valueType); var dictionary = InvokeGenerator(type, generator) as IReadOnlyDictionary; dictionary.Should().NotBeNull().And.NotContainNulls(); foreach (int key in dictionary.Keys) { - string? value = dictionary[key]; + string value = dictionary[key]; key.Should().BeOfType(keyType); value.Should().BeOfType(valueType); @@ -48,13 +48,13 @@ public void Generate_Should_Return_Dictionary(Type type) [InlineData(typeof(ReadOnlyDictionary))] public void GetGenerator_Should_Return_ReadOnlyDictionaryGenerator(Type type) { - AutoFakerContext? context = CreateContext(type); - Type[]? genericTypes = type.GetGenericArguments(); - Type? keyType = genericTypes.ElementAt(0); - Type? valueType = genericTypes.ElementAt(1); - Type? generatorType = GetGeneratorType(typeof(ReadOnlyDictionaryGenerator<,>), keyType, valueType); + AutoFakerContext context = CreateContext(type); + Type[] genericTypes = type.GetGenericArguments(); + Type keyType = genericTypes.ElementAt(0); + Type valueType = genericTypes.ElementAt(1); + Type generatorType = GetGeneratorType(typeof(ReadOnlyDictionaryGenerator<,>), keyType, valueType); - GeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); } } } \ No newline at end of file diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs index c7acdbc..e292c89 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoGeneratorsFixture.cs @@ -4,7 +4,9 @@ using System.Dynamic; using System.Linq; using System.Reflection; +using Bogus; using FluentAssertions; +using Soenneker.Reflection.Cache.Types; using Soenneker.Utils.AutoBogus.Config; using Soenneker.Utils.AutoBogus.Context; using Soenneker.Utils.AutoBogus.Generators; @@ -13,6 +15,7 @@ using Soenneker.Utils.AutoBogus.Generators.Abstract; using Soenneker.Utils.AutoBogus.Generators.Types; using Soenneker.Utils.AutoBogus.Tests.Extensions; +using Soenneker.Utils.AutoBogus.Services; namespace Soenneker.Utils.AutoBogus.Tests; @@ -68,9 +71,9 @@ public static IEnumerable ListOfReadOnlyDictionaryTypes { get { - yield return new[] { typeof(NonGeneric) }; - yield return new[] { typeof(OneArgument) }; - yield return new[] { typeof(TwoArgumentsThatAreDifferentFromBaseReadOnlyDictionaryClass) }; + yield return new[] {typeof(NonGeneric)}; + yield return new[] {typeof(OneArgument)}; + yield return new[] {typeof(TwoArgumentsThatAreDifferentFromBaseReadOnlyDictionaryClass)}; } } @@ -81,10 +84,10 @@ public void Should_Handle_Subclasses(Type readOnlyDictionaryType) // Arrange var config = new AutoFakerConfig(); - var context = new AutoFakerContext(config, readOnlyDictionaryType); + var context = new AutoFakerContext(config, new Faker(), new AutoFakerBinder(config), readOnlyDictionaryType); // Act - IAutoFakerGenerator generator = GeneratorFactory.ResolveGenerator(context); + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.CreateGenerator(context); object instance = generator.Generate(context); @@ -113,9 +116,9 @@ public static IEnumerable ListOfDictionaryTypes { get { - yield return new[] { typeof(NonGeneric) }; - yield return new[] { typeof(OneArgument) }; - yield return new[] { typeof(TwoArgumentsThatAreDifferentFromBaseDictionaryClass) }; + yield return new[] {typeof(NonGeneric)}; + yield return new[] {typeof(OneArgument)}; + yield return new[] {typeof(TwoArgumentsThatAreDifferentFromBaseDictionaryClass)}; } } @@ -126,10 +129,10 @@ public void Should_Handle_Subclasses(Type dictionaryType) // Arrange var config = new AutoFakerConfig(); - var context = new AutoFakerContext(config, dictionaryType); + var context = new AutoFakerContext(config, new Faker(), new AutoFakerBinder(config), dictionaryType); // Act - IAutoFakerGenerator generator = GeneratorFactory.ResolveGenerator(context); + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.CreateGenerator(context); object instance = generator.Generate(context); @@ -155,8 +158,8 @@ public static IEnumerable ListOfSetTypes { get { - yield return new[] { typeof(NonGeneric) }; - yield return new[] { typeof(GenericWithDifferentType) }; + yield return new[] {typeof(NonGeneric)}; + yield return new[] {typeof(GenericWithDifferentType)}; } } @@ -164,15 +167,15 @@ public static IEnumerable ListOfSetTypes [MemberData(nameof(ListOfSetTypes))] public void Should_Handle_Subclasses(Type setType) { - // Arrange var config = new AutoFakerConfig(); - var context = new AutoFakerContext(config); + // Arrange + var context = new AutoFakerContext(config, new Faker(), new AutoFakerBinder(config)); context.Setup(setType); // Act - IAutoFakerGenerator generator = GeneratorFactory.ResolveGenerator(context); + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.CreateGenerator(context); object instance = generator.Generate(context); @@ -198,8 +201,8 @@ public static IEnumerable ListOfListTypes { get { - yield return new[] { typeof(NonGeneric) }; - yield return new[] { typeof(GenericWithDifferentType) }; + yield return new[] {typeof(NonGeneric)}; + yield return new[] {typeof(GenericWithDifferentType)}; } } @@ -210,12 +213,12 @@ public void Should_Handle_Subclasses(Type listType) // Arrange var config = new AutoFakerConfig(); - var context = new AutoFakerContext(config); + var context = new AutoFakerContext(config, new Faker(), new AutoFakerBinder(config)); context.Setup(listType); // Act - IAutoFakerGenerator generator = GeneratorFactory.ResolveGenerator(context); + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.CreateGenerator(context); object instance = generator.Generate(context); @@ -233,7 +236,8 @@ public class ReferenceTypes private sealed class TestClass { public TestClass(in int value) - { } + { + } } [Fact] @@ -244,7 +248,7 @@ public void Should_Not_Throw_For_Reference_Types() ParameterInfo parameter = constructor.GetParameters().Single(); AutoFakerContext context = CreateContext(parameter.ParameterType); - Action action = () => GeneratorFactory.GetGenerator(context); + Action action = () => AutoFakerGeneratorFactory.GetGenerator(context); action.Should().NotThrow(); } } @@ -256,7 +260,8 @@ public class RegisteredGenerator [MemberData(nameof(GetRegisteredTypes))] public void Generate_Should_Return_Value(Type type) { - IAutoFakerGenerator generator = GeneratorFactory.Generators[type]; + CachedType cachedType = CacheService.Cache.GetCachedType(type); + IAutoFakerGenerator generator = GeneratorService.GetFundamentalGenerator(cachedType); InvokeGenerator(type, generator).Should().BeOfType(type); } @@ -265,18 +270,18 @@ public void Generate_Should_Return_Value(Type type) [MemberData(nameof(GetRegisteredTypes))] public void GetGenerator_Should_Return_Generator(Type type) { + CachedType cachedType = CacheService.Cache.GetCachedType(type); AutoFakerContext context = CreateContext(type); - IAutoFakerGenerator generator = GeneratorFactory.Generators[type]; + IAutoFakerGenerator generator = GeneratorService.GetFundamentalGenerator(cachedType); + + GeneratorService.Clear(); - GeneratorFactory.GetGenerator(context).Should().Be(generator); + AutoFakerGeneratorFactory.GetGenerator(context).Should().Be(generator); } public static IEnumerable GetRegisteredTypes() { - return GeneratorFactory.Generators.Select(g => new object[] - { - g.Key - }); + return GeneratorService.GetSupportedFundamentalTypes().Select(c => new object[] {c}); } [Theory] @@ -287,7 +292,7 @@ public void GetGenerator_Should_Return_Generator_For_DataSets_And_DataTables(Typ AutoFakerContext context = CreateContext(dataType); // Act - IAutoFakerGenerator generator = GeneratorFactory.GetGenerator(context); + IAutoFakerGenerator generator = AutoFakerGeneratorFactory.GetGenerator(context); // Assert generator.Should().BeAssignableTo(generatorType); @@ -295,11 +300,11 @@ public void GetGenerator_Should_Return_Generator_For_DataSets_And_DataTables(Typ public static IEnumerable GetDataSetAndDataTableTypes() { - yield return new object[] { typeof(System.Data.DataSet), typeof(DataSetGenerator) }; - yield return new object[] { typeof(DataSetGeneratorFacet.TypedDataSet), typeof(DataSetGenerator) }; - yield return new object[] { typeof(System.Data.DataTable), typeof(DataTableGenerator) }; - yield return new object[] { typeof(DataTableGeneratorFacet.TypedDataTable1), typeof(DataTableGenerator) }; - yield return new object[] { typeof(DataTableGeneratorFacet.TypedDataTable2), typeof(DataTableGenerator) }; + yield return new object[] {typeof(System.Data.DataSet), typeof(DataSetGenerator)}; + yield return new object[] {typeof(DataSetGeneratorFacet.TypedDataSet), typeof(DataSetGenerator)}; + yield return new object[] {typeof(System.Data.DataTable), typeof(DataTableGenerator)}; + yield return new object[] {typeof(DataTableGeneratorFacet.TypedDataTable1), typeof(DataTableGenerator)}; + yield return new object[] {typeof(DataTableGeneratorFacet.TypedDataTable2), typeof(DataTableGenerator)}; } } @@ -335,7 +340,7 @@ public void GetGenerator_Should_Return_NullableGenerator() Type type = typeof(ExpandoObject); AutoFakerContext context = CreateContext(type); - GeneratorFactory.GetGenerator(context).Should().BeOfType(); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(); } } @@ -351,6 +356,7 @@ public class ArrayGenerator public void Generate_Should_Return_Array(Type type) { Type? itemType = type.GetElementType(); + AutoFakerBinderService.SetBinder(new AutoFakerBinder(new AutoFakerConfig())); IAutoFakerGenerator generator = CreateGenerator(typeof(ArrayGenerator<>), itemType); var array = InvokeGenerator(type, generator) as Array; @@ -369,7 +375,7 @@ public void GetGenerator_Should_Return_ArrayGenerator(Type type) Type? itemType = type.GetElementType(); Type generatorType = GetGeneratorType(typeof(ArrayGenerator<>), itemType); - GeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); } } @@ -391,7 +397,7 @@ public void GetGenerator_Should_Return_EnumGenerator() Type type = typeof(TestEnum); AutoFakerContext context = CreateContext(type); - GeneratorFactory.GetGenerator(context).Should().BeOfType>(); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType>(); } } @@ -411,6 +417,7 @@ public void Generate_Should_Return_Dictionary(Type type) Type[] genericTypes = type.GetGenericArguments(); Type keyType = genericTypes.ElementAt(0); Type valueType = genericTypes.ElementAt(1); + AutoFakerBinderService.SetBinder(new AutoFakerBinder(new AutoFakerConfig())); IAutoFakerGenerator generator = CreateGenerator(typeof(DictionaryGenerator<,>), keyType, valueType); var dictionary = InvokeGenerator(type, generator) as IDictionary; @@ -441,7 +448,7 @@ public void GetGenerator_Should_Return_DictionaryGenerator(Type type) Type valueType = genericTypes.ElementAt(1); Type generatorType = GetGeneratorType(typeof(DictionaryGenerator<,>), keyType, valueType); - GeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); } } @@ -464,6 +471,7 @@ public void Generate_Should_Return_List(Type type) { Type[] genericTypes = type.GetGenericArguments(); Type itemType = genericTypes.ElementAt(0); + AutoFakerBinderService.SetBinder(new AutoFakerBinder(new AutoFakerConfig())); IAutoFakerGenerator generator = CreateGenerator(typeof(ListGenerator<>), itemType); var list = InvokeGenerator(type, generator) as IEnumerable; @@ -489,7 +497,7 @@ public void GetGenerator_Should_Return_ListGenerator(Type type) Type itemType = genericTypes.ElementAt(0); Type generatorType = GetGeneratorType(typeof(ListGenerator<>), itemType); - GeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); } } @@ -507,6 +515,7 @@ public void Generate_Should_Return_Set(Type type) { Type[] genericTypes = type.GetGenericArguments(); Type itemType = genericTypes.ElementAt(0); + AutoFakerBinderService.SetBinder(new AutoFakerBinder(new AutoFakerConfig())); IAutoFakerGenerator generator = CreateGenerator(typeof(SetGenerator<>), itemType); var set = InvokeGenerator(type, generator) as IEnumerable; @@ -525,9 +534,11 @@ public void GetGenerator_Should_Return_SetGenerator(Type type) AutoFakerContext context = CreateContext(type); Type[] genericTypes = type.GetGenericArguments(); Type itemType = genericTypes.ElementAt(0); + AutoFakerBinderService.SetBinder(new AutoFakerBinder(new AutoFakerConfig())); Type generatorType = GetGeneratorType(typeof(SetGenerator<>), itemType); - GeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); + + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); } } @@ -544,6 +555,7 @@ public void Generate_Should_Return_Enumerable(Type type) { Type[] genericTypes = type.GetGenericArguments(); Type itemType = genericTypes.ElementAt(0); + AutoFakerBinderService.SetBinder(new AutoFakerBinder(new AutoFakerConfig())); IAutoFakerGenerator generator = CreateGenerator(typeof(EnumerableGenerator<>), itemType); var enumerable = InvokeGenerator(type, generator) as IEnumerable; @@ -563,7 +575,7 @@ public void GetGenerator_Should_Return_EnumerableGenerator(Type type) Type itemType = genericTypes.ElementAt(0); Type generatorType = GetGeneratorType(typeof(EnumerableGenerator<>), itemType); - GeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); } } @@ -585,7 +597,7 @@ public void GetGenerator_Should_Return_NullableGenerator() Type type = typeof(TestEnum?); AutoFakerContext context = CreateContext(type); - GeneratorFactory.GetGenerator(context).Should().BeOfType>(); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType>(); } } @@ -599,6 +611,7 @@ public class TypeGenerator [InlineData(typeof(TestAbstractClass))] public void Generate_Should_Return_Value(Type type) { + AutoFakerBinderService.SetBinder(new AutoFakerBinder(new AutoFakerConfig())); IAutoFakerGenerator generator = CreateGenerator(typeof(TypeGenerator<>), type); if (type.IsInterface() || type.IsAbstract()) @@ -621,20 +634,20 @@ public void GetGenerator_Should_Return_TypeGenerator(Type type) AutoFakerContext context = CreateContext(type); Type generatorType = GetGeneratorType(typeof(TypeGenerator<>), type); - GeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(generatorType); } } public class GeneratorOverrides : AutoGeneratorsFixture { - private GeneratorOverride _generatorOverride; - private List _overrides; + private AutoFakerGeneratorOverride _autoFakerGeneratorOverride; + private List _overrides; - private class TestGeneratorOverride - : GeneratorOverride + private class TestAutoFakerGeneratorOverride + : AutoFakerGeneratorOverride { - public TestGeneratorOverride(bool shouldOverride = false) + public TestAutoFakerGeneratorOverride(bool shouldOverride = false) { ShouldOverride = shouldOverride; } @@ -646,51 +659,54 @@ public override bool CanOverride(AutoFakerContext context) return ShouldOverride; } - public override void Generate(AutoFakerContextOverride context) - { } + public override void Generate(AutoFakerOverrideContext context) + { + } } public GeneratorOverrides() { - _generatorOverride = new TestGeneratorOverride(true); - _overrides = new List + _autoFakerGeneratorOverride = new TestAutoFakerGeneratorOverride(true); + _overrides = new List { - new TestGeneratorOverride(), - _generatorOverride, - new TestGeneratorOverride() + new TestAutoFakerGeneratorOverride(), + _autoFakerGeneratorOverride, + new TestAutoFakerGeneratorOverride() }; } [Fact] public void Should_Return_All_Matching_Overrides() { - var generatorOverride = new TestGeneratorOverride(true); + var generatorOverride = new TestAutoFakerGeneratorOverride(true); _overrides.Insert(1, generatorOverride); + GeneratorService.Clear(); + AutoFakerContext context = CreateContext(typeof(string), _overrides); - var invoker = GeneratorFactory.GetGenerator(context) as GeneratorOverrideInvoker; + var invoker = AutoFakerGeneratorFactory.GetGenerator(context) as AutoFakerGeneratorOverrideInvoker; - invoker.Overrides.Should().BeEquivalentTo(new[] { generatorOverride, _generatorOverride }); + invoker.Overrides.Should().BeEquivalentTo(new[] {generatorOverride, _autoFakerGeneratorOverride}); } [Fact] public void Should_Return_Generator_If_No_Matching_Override() { - _overrides = new List + _overrides = new List { - new TestGeneratorOverride() + new TestAutoFakerGeneratorOverride() }; AutoFakerContext context = CreateContext(typeof(int), _overrides); - GeneratorFactory.GetGenerator(context).Should().BeOfType(); + AutoFakerGeneratorFactory.GetGenerator(context).Should().BeOfType(); } [Fact] public void Should_Invoke_Generator() { AutoFakerContext context = CreateContext(typeof(string), _overrides); - IAutoFakerGenerator generatorOverride = GeneratorFactory.GetGenerator(context); + IAutoFakerGenerator generatorOverride = AutoFakerGeneratorFactory.GetGenerator(context); generatorOverride.Generate(context).Should().BeOfType().And.NotBeNull(); } @@ -712,10 +728,10 @@ private static Type GetGeneratorType(Type type, params Type[] types) private static IAutoFakerGenerator CreateGenerator(Type type, params Type[] types) { type = GetGeneratorType(type, types); - return (IAutoFakerGenerator)Activator.CreateInstance(type); + return (IAutoFakerGenerator) Activator.CreateInstance(type); } - private static AutoFakerContext CreateContext(Type type, List? generatorOverrides = null, Func? dataTableRowCountFunctor = null) + private static AutoFakerContext CreateContext(Type type, List? generatorOverrides = null, int? dataTableRowCountFunctor = null) { var config = new AutoFakerConfig(); @@ -726,9 +742,9 @@ private static AutoFakerContext CreateContext(Type type, List if (dataTableRowCountFunctor != null) { - config.DataTableRowCount = dataTableRowCountFunctor; + config.DataTableRowCount = dataTableRowCountFunctor.Value; } - return new AutoFakerContext(config, type); + return new AutoFakerContext(config, new Faker(), new AutoFakerBinder(config), type); } } \ No newline at end of file diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs b/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs index 16e553c..607da6f 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/Benchmarking/Benchmarks/GenerateBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using Soenneker.Utils.AutoBogus.Abstract; using Soenneker.Utils.AutoBogus.Tests.Dtos.Complex; -using Soenneker.Utils.AutoBogus.Tests.Dtos.Simple; namespace Soenneker.Utils.AutoBogus.Tests.Benchmarking.Benchmarks; @@ -12,7 +11,7 @@ public class GenerateBenchmarks [GlobalSetup] public void Setup() { - _autoFaker = AutoFaker.Create(); + _autoFaker = new AutoFaker(); } [Benchmark(Baseline = true)] @@ -21,21 +20,21 @@ public Order Generate_complex() return _autoFaker.Generate(); } - [Benchmark] - public TestClassWithSingleProperty Generate_simple_reference() - { - return _autoFaker.Generate>(); - } + //[Benchmark] + //public TestClassWithSingleProperty Generate_simple_reference() + //{ + // return _autoFaker.Generate>(); + //} - [Benchmark] - public int Generate_int() - { - return _autoFaker.Generate(); - } + //[Benchmark] + //public int Generate_int() + //{ + // return _autoFaker.Generate(); + //} - [Benchmark] - public string Generate_string() - { - 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/GenerateAssertions.cs b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/GenerateAssertions.cs index 2d915ac..1cf44b7 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/Dtos/GenerateAssertions.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/GenerateAssertions.cs @@ -19,7 +19,7 @@ public sealed class GenerateAssertions : ReferenceTypeAssertions BeGenerated() { - Type? type = Subject.GetType(); - Func? assertion = GetAssertion(type); + Type type = Subject.GetType(); + Func assertion = GetAssertion(type); Scope = Execute.Assertion; @@ -95,8 +95,8 @@ public AndConstraint BeGeneratedWithoutMocks() public AndConstraint NotBeGenerated() { - Type? type = Subject.GetType(); - IEnumerable? memberInfos = GetMemberInfos(type); + Type type = Subject.GetType(); + IEnumerable memberInfos = GetMemberInfos(type); Scope = Execute.Assertion; @@ -110,8 +110,8 @@ public AndConstraint NotBeGenerated() private AndConstraint AssertSubject() { - Type? type = Subject.GetType(); - Func? assertion = GetAssertion(type); + Type type = Subject.GetType(); + Func assertion = GetAssertion(type); Scope = Execute.Assertion; @@ -123,7 +123,7 @@ private AndConstraint AssertSubject() private string AssertType(string path, Type type, object instance) { // Iterate the members for the instance and assert their values - IEnumerable? members = GetMemberInfos(type); + IEnumerable members = GetMemberInfos(type); foreach (MemberInfo? member in members) { @@ -138,7 +138,7 @@ private void AssertDefaultValue(MemberInfo memberInfo) ExtractMemberInfo(memberInfo, out Type memberType, out Func memberGetter); // Resolve the default value for the current member type and check it matches - MethodInfo? factory = DefaultValueFactory.MakeGenericMethod(memberType); + MethodInfo factory = DefaultValueFactory.MakeGenericMethod(memberType); object? defaultValue = factory.Invoke(this, new object[0]); object? value = memberGetter.Invoke(Subject); bool equal = value == null && defaultValue == null; @@ -224,8 +224,8 @@ private static string AssertString(string path, Type type, object value) private string AssertNullable(string path, Type type, object value) { - Type? genericType = type.GenericTypeArguments.Single(); - Func? assertion = GetAssertion(genericType); + Type genericType = type.GenericTypeArguments.Single(); + Func assertion = GetAssertion(genericType); return assertion.Invoke(path, genericType, value); } @@ -238,7 +238,7 @@ private string AssertMock(string path, Type type, object value) } // Assert via assignment rather than explicit checks (the actual instance could be a sub class) - Type? valueType = value.GetType(); + Type valueType = value.GetType(); return type.IsAssignableFrom(valueType) ? null : GetAssertionMessage(path, type, value); } @@ -250,9 +250,9 @@ private string AssertArray(string path, Type type, object value) private string AssertDictionary(string path, Type type, object value) { - Type[]? genericTypes = type.GetGenericArguments(); - Type? keyType = genericTypes.ElementAt(0); - Type? valueType = genericTypes.ElementAt(1); + Type[] genericTypes = type.GetGenericArguments(); + Type keyType = genericTypes.ElementAt(0); + Type valueType = genericTypes.ElementAt(1); var dictionary = value as IDictionary; if (dictionary == null) @@ -273,8 +273,8 @@ private string AssertDictionary(string path, Type type, object value) private string AssertEnumerable(string path, Type type, object value) { - Type[]? genericTypes = type.GetGenericArguments(); - Type? itemType = genericTypes.Single(); + Type[] genericTypes = type.GetGenericArguments(); + Type itemType = genericTypes.Single(); return AssertItems(path, itemType, value as IEnumerable); } @@ -289,7 +289,7 @@ private string AssertItems(string path, Type type, IEnumerable items, string ele // Check the count state of the items var count = 0; - IEnumerator? enumerator = items.GetEnumerator(); + IEnumerator enumerator = items.GetEnumerator(); while (enumerator.MoveNext()) { @@ -300,11 +300,11 @@ private string AssertItems(string path, Type type, IEnumerable items, string ele { // If we have any items, check each of them var index = 0; - Func? assertion = GetAssertion(type); + Func assertion = GetAssertion(type); foreach (object? item in items) { - string? element = string.Format("{0}[{1}]{2}", path, index++, suffix); + string element = string.Format("{0}[{1}]{2}", path, index++, suffix); string? message = assertion.Invoke(element, type, item); if (message != null) @@ -335,8 +335,8 @@ private void AssertMember(string path, MemberInfo memberInfo, object instance) path = string.Concat(path, ".", memberInfo.Name); // Resolve the assertion and value for the member type - object? value = memberGetter.Invoke(instance); - Func? assertion = GetAssertion(memberType); + object value = memberGetter.Invoke(instance); + Func assertion = GetAssertion(memberType); string? message = assertion.Invoke(path, memberType, value); // Register an assertion for each member @@ -380,8 +380,8 @@ private static bool IsType(Type type, Type baseType) // We may need to do some generics magic to compare the types if (type.IsGenericType() && baseType.IsGenericType()) { - Type[]? types = type.GetGenericArguments(); - Type[]? baseTypes = baseType.GetGenericArguments(); + Type[] types = type.GetGenericArguments(); + Type[] baseTypes = baseType.GetGenericArguments(); if (types.Length == baseTypes.Length) { diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TypeExtensionTests.cs b/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TypeExtensionTests.cs index 8d6a264..ff3596c 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TypeExtensionTests.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/Extensions/TypeExtensionTests.cs @@ -18,9 +18,9 @@ public void IsDictionary_should_be_true() { Type derivedType = typeof(DerivedDictionary); - var cachedType = CacheService.Cache.GetCachedType(derivedType); + CachedType cachedType = CacheService.Cache.GetCachedType(derivedType); - bool result = cachedType.IsDictionary(); + bool result = cachedType.IsDictionary; result.Should().BeTrue(); } @@ -62,9 +62,9 @@ public void GetTypeOfGenericCollectionFromInterfaceTypes_should_return_dictionar public void IsReadOnlyDictionary_should_be_true() { Type derivedType = typeof(DerivedReadOnlyDictionary); - var cachedType = CacheService.Cache.GetCachedType(derivedType); + CachedType cachedType = CacheService.Cache.GetCachedType(derivedType); - bool result = cachedType.IsReadOnlyDictionary(); + bool result = cachedType.IsReadOnlyDictionary; result.Should().BeTrue(); } } \ No newline at end of file diff --git a/test/Soenneker.Utils.AutoBogus.Tests/GenericTypeUtilTests.cs b/test/Soenneker.Utils.AutoBogus.Tests/GenericTypeUtilTests.cs index faa313b..7247568 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/GenericTypeUtilTests.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/GenericTypeUtilTests.cs @@ -10,7 +10,7 @@ public class GenericTypeUtilTests [Fact] public void Generate_should_generate() { - IAutoFaker? faker = AutoFaker.Create(); + IAutoFaker faker = new AutoFaker(); var order1 = faker.Generate(); order1.Should().NotBeNull(); diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Playground/NodaTimeFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/Playground/NodaTimeFixture.cs index d79451b..1676731 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/Playground/NodaTimeFixture.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/Playground/NodaTimeFixture.cs @@ -49,7 +49,7 @@ public void TestFaker() [Fact] public void TestAutoFaker() { - var faker = new Faker().RuleFor(x => x.Time, faker => _validDate); + Faker? faker = new Faker().RuleFor(x => x.Time, faker => _validDate); TimeHolder? created = faker.Generate(); created = faker.Generate(); diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Playground/StructFixture.cs b/test/Soenneker.Utils.AutoBogus.Tests/Playground/StructFixture.cs index a22e346..1c84a15 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/Playground/StructFixture.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/Playground/StructFixture.cs @@ -19,7 +19,7 @@ public StructFixture(ITestOutputHelper outputHelper) [Fact] public void Generate_ExampleStruct() { - IAutoFaker faker = AutoFaker.Create(builder => + IAutoFaker faker = new AutoFaker(builder => { builder.WithOverride(new ExampleStructOverride()); }); @@ -32,7 +32,7 @@ public void Generate_ExampleStruct() } } -class ExampleStructOverride : GeneratorOverride +class ExampleStructOverride : AutoFakerGeneratorOverride { public override bool Preinitialize => false; @@ -41,7 +41,7 @@ public override bool CanOverride(AutoFakerContext context) return context.GenerateType == typeof(ExampleStruct); } - public override void Generate(AutoFakerContextOverride context) + public override void Generate(AutoFakerOverrideContext context) { context.Instance = new ExampleStruct(5); } 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 b66fdc1..eeee848 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/Soenneker.Utils.AutoBogus.Tests.csproj +++ b/test/Soenneker.Utils.AutoBogus.Tests/Soenneker.Utils.AutoBogus.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0