Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed improvements #45

Merged
merged 9 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ 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

```
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<T>` was dropped from this package.
⚠️ A Bogus `Faker` takes a long time to initialize, so AutoFaker will mirror Faker in this sense. Thus, `AutoFaker<T>` 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.
10 changes: 8 additions & 2 deletions src/Abstract/IAutoFaker.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,13 +11,17 @@ namespace Soenneker.Utils.AutoBogus.Abstract;
/// </summary>
public interface IAutoFaker
{
void SetConfig(AutoFakerConfig config);

void SetFaker(Faker faker);

/// <summary>
/// Generates an instance of type <typeparamref name="TType"/>.
/// </summary>
/// <typeparam name="TType">The type of instance to generate.</typeparam>
/// <param name="configure">A handler to build the generate request configuration.</param>
/// <returns>The generated instance.</returns>
TType Generate<TType>(Action<IAutoGenerateConfigBuilder> configure = null);
TType Generate<TType>(Action<IAutoGenerateConfigBuilder>? configure = null);

/// <summary>
/// Generates a collection of instances of type <typeparamref name="TType"/>.
Expand All @@ -24,5 +30,5 @@ public interface IAutoFaker
/// <param name="count">The number of instances to generate.</param>
/// <param name="configure">A handler to build the generate request configuration.</param>
/// <returns>The generated collection of instances.</returns>
List<TType> Generate<TType>(int count, Action<IAutoGenerateConfigBuilder> configure = null);
List<TType> Generate<TType>(int count, Action<IAutoGenerateConfigBuilder>? configure = null);
}
12 changes: 2 additions & 10 deletions src/Abstract/IAutoFakerBinder.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System;
using System.Reflection;
using Bogus;
using Soenneker.Utils.AutoBogus.Context;

namespace Soenneker.Utils.AutoBogus.Abstract;

/// <summary>
/// An interface for binding generated instances.
/// </summary>
public interface IAutoFakerBinder : IBinder
public interface IAutoFakerBinder
{
/// <summary>
/// Creates an instance of <typeparamref name="TType"/>.
Expand All @@ -18,20 +15,15 @@ public interface IAutoFakerBinder : IBinder
/// <returns>The created instance.</returns>
TType? CreateInstance<TType>(AutoFakerContext context);

object? CreateInstance(AutoFakerContext context, Type type);

/// <summary>
/// Populates the provided instance with generated values.
/// </summary>
/// <typeparam name="TType">The type of instance to populate.</typeparam>
/// <param name="instance">The instance to populate.</param>
/// <param name="context">The <see cref="AutoFakerContext"/> instance for the generate request.</param>
/// <param name="members">An optional collection of members to populate. If null, all writable instance members are populated.</param>
/// <remarks>
/// Due to the boxing nature of value types, the <paramref name="instance"/> parameter is an object. This means the populated
/// values are applied to the provided instance and not a copy.
/// </remarks>
void PopulateInstance<TType>(object instance, AutoFakerContext context, MemberInfo[]? members = null);

void PopulateInstance(object instance, AutoFakerContext context, Type type, MemberInfo[]? members = null);
void PopulateInstance<TType>(object instance, AutoFakerContext context);
}
76 changes: 41 additions & 35 deletions src/AutoFaker.cs
Original file line number Diff line number Diff line change
@@ -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;

///<inheritdoc cref="IAutoFaker"/>
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<IAutoGenerateConfigBuilder>? 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<TType>(Action<IAutoGenerateConfigBuilder> configure)
TType IAutoFaker.Generate<TType>(Action<IAutoGenerateConfigBuilder>? configure)
{
AutoFakerContext context = CreateContext(configure);
return context.Generate<TType>();
}

List<TType> IAutoFaker.Generate<TType>(int count, Action<IAutoGenerateConfigBuilder> configure)
List<TType> IAutoFaker.Generate<TType>(int count, Action<IAutoGenerateConfigBuilder>? configure)
{
AutoFakerContext context = CreateContext(configure);
return context.GenerateMany<TType>(count);
Expand All @@ -35,43 +60,25 @@ List<TType> IAutoFaker.Generate<TType>(int count, Action<IAutoGenerateConfigBuil
/// Configures all faker instances and generate requests.
/// </summary>
/// <param name="configure">A handler to build the default faker configuration.</param>
public static void Configure(Action<IAutoFakerDefaultConfigBuilder>? configure)
public void Configure(Action<IAutoFakerDefaultConfigBuilder>? configure)
{
if (configure == null)
return;

var builder = new AutoFakerConfigBuilder(DefaultConfigService.Config);
var builder = new AutoFakerConfigBuilder(Config, this);
configure.Invoke(builder);
}

/// <summary>
/// Creates a configured <see cref="IAutoFaker"/> instance.
/// </summary>
/// <param name="configure">A handler to build the faker configuration.</param>
/// <returns>The configured <see cref="IAutoFaker"/> instance.</returns>
public static AutoFaker Create(Action<IAutoGenerateConfigBuilder>? 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);
}

/// <summary>
/// Generates an instance of type <typeparamref name="TType"/>.
/// </summary>
/// <typeparam name="TType">The type of instance to generate.</typeparam>
/// <param name="configure">A handler to build the generate request configuration.</param>
/// <returns>The generated instance.</returns>
[Obsolete("This creates a new Bogus.Faker on each call (expensive); use one AutoFaker across your context")]
public static TType Generate<TType>(Action<IAutoGenerateConfigBuilder>? configure = null)
{
IAutoFaker faker = Create(configure);
IAutoFaker faker = new AutoFaker(configure);
return faker.Generate<TType>();
}

Expand All @@ -82,22 +89,21 @@ public static TType Generate<TType>(Action<IAutoGenerateConfigBuilder>? configur
/// <param name="count">The number of instances to generate.</param>
/// <param name="configure">A handler to build the generate request configuration.</param>
/// <returns>The generated collection of instances.</returns>
[Obsolete("This creates a new Bogus.Faker on each call (expensive); use one AutoFaker across your context")]
public static List<TType> Generate<TType>(int count, Action<IAutoGenerateConfigBuilder>? configure = null)
{
IAutoFaker faker = Create(configure);
IAutoFaker faker = new AutoFaker(configure);
return faker.Generate<TType>(count);
}

private AutoFakerContext CreateContext(Action<IAutoGenerateConfigBuilder>? 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);
}
}
Loading
Loading