TryAtSoftware.Randomizer 1.0.4

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package TryAtSoftware.Randomizer --version 1.0.4                
NuGet\Install-Package TryAtSoftware.Randomizer -Version 1.0.4                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TryAtSoftware.Randomizer" Version="1.0.4" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add TryAtSoftware.Randomizer --version 1.0.4                
#r "nuget: TryAtSoftware.Randomizer, 1.0.4"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install TryAtSoftware.Randomizer as a Cake Addin
#addin nuget:?package=TryAtSoftware.Randomizer&version=1.0.4

// Install TryAtSoftware.Randomizer as a Cake Tool
#tool nuget:?package=TryAtSoftware.Randomizer&version=1.0.4                

Quality Gate Status Reliability Rating Security Rating Maintainability Rating Vulnerabilities Bugs

Core validation

About the project

TryAtSoftware.Randomizer is a library that should simplify the process of random values generation. We offer a set of methods and components that can be used to generate random values of different types. They are reusable and can be applied to every projects of yours.

About us

Try At Software is a software development company based in Bulgaria. We are mainly using dotnet technologies (C#, ASP.NET Core, Entity Framework Core, etc.) and our main idea is to provide a set of tools that can simplify the majority of work a developer does on a daily basis.

Getting started

Installing the package

Before creating any randomizers, you need to install the package. The simplest way to do this is to either use the NuGet package manager, or the dotnet CLI.

Using the NuGet package manager console within Visual Studio, you can install the package using the following command:

Install-Package TryAtSoftware.Randomizer

Or using the dotnet CLI from a terminal window:

dotnet add package TryAtSoftware.Randomizer

Creating your first randomizer

To define a randomizer, you need to create a class that implements the IRandomizer<T> interface, where T is the type of information this component should be responsible for randomizing. For example, imagine that you want to create a randomizer that generates a random DateTime instance in the future. You would need the following class:

using System;
using TryAtSoftware.Randomizer.Core.Helpers;
using TryAtSoftware.Randomizer.Core.Interfaces;

public class DateTimeRandomizer : IRandomizer<DateTime>
{
    private readonly DateTime _instantiationTime = DateTime.Now;

    public DateTime PrepareRandomValue()
    {
        // We want to generate a random DateTime instance that is a few minutes ahead of our current time.
        var randomOffsetInMinutes = RandomizationHelper.RandomInteger(15, 60);
        return this._instantiationTime.AddMinutes(randomOffsetInMinutes);
    }
}

Then you can use this randomizer as follows:

var dateTimeRandomizer = new DateTimeRandomizer();
for (int i = 0; i < 5; i++)
{
    var randomDateTime = dateTimeRandomizer.PrepareRandomValue();
    Console.WriteLine(randomDateTime);
}

If you run this code, you will see that the output is a few random DateTime instances. You may notice that the output sometimes may contain a value more than once. This is because the strength of our randomizer is not great. If we analyze it more deeply, we can see that it can generate only 45 different values by design. We will discuss various mechanisms to increase the strength of our randomizers in some of the next sections.

Randomizing complex types

As you saw in the previous chapter, writing standard randomizers for simple types is easy - you just implement a single method and that's it. Randomizing complex types is not a more complex operation. We have provided you whit a base class that you can use to implement your own complex randomizers. It is called ComplexRandomizer<T> where T is the complex type it should be responsible for randomizing.

Let's start with a basic example! For simplicity, we will work with this model:

using System;

public class Person
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public bool IsEmployed { get; set; }
    public int Age { get; set; }
    public DateTimeOffset EventDate { get; set; }
}

Our complex randomizer will look like this:

using TryAtSoftware.Randomizer.Core;
using TryAtSoftware.Randomizer.Core.Primitives;

public class PersonRandomizer : ComplexRandomizer<Person>
{
    public PersonRandomizer()
    {
        this.AddRandomizationRule(p => p.Id, new GuidRandomizer());
        this.AddRandomizationRule(p => p.Name, new StringRandomizer());
        this.AddRandomizationRule(p => p.Age, new NumberRandomizer());
        this.AddRandomizationRule(p => p.IsEmployed, new BooleanRandomizer());
        this.AddRandomizationRule(p => p.EventDate, new DateTimeOffsetRandomizer());
    }
}

Let's examine this complex randomizer!

We can see that it can be used to define a specific randomizer for each publicly exposed member of the Person type. And actually this is the main idea of our library. This way we can reuse already defined randomizers for different types. We can combine them to create complex randomizers that can generate random instances of any type. Isn't that great?!

If we want to examine the complex randomization process more deeply, we can see that it is contained of two phases that we will describe in the next sections.

Instance building phase

The IInstanceBuilder<T> is a component responsible for instantiating the complex type. By default, a GeneralInstanceBuilder<T> will be used if none is specified. This is the recommended option of instance building as it is implemented to find the most suitable constructor and invoke it (so you do not have to write any additional code). Furthermore, it tracks down the used parameters so the randomization rules defining them will not be used during the next phase of the complex randomization process.

However, if you want to implement one by yourself, you have a few options:

  • You can implement the IInstanceBuilder<Person> interface and define some custom instantiation logic. If you chose this option, you are in full control of the instantiation process.
using TryAtSoftware.Randomizer.Core;
using TryAtSoftware.Randomizer.Core.Interfaces;

public class PersonInstanceBuilder : IInstanceBuilder<Person>
{
    public IInstanceBuildingResult<Person> PrepareNewInstance(IInstanceBuildingArguments arguments)
    {
        // You can use the provided instance building arguments to customize the instance.
        // Note that if you do so, the returned instance building result may need some changes.
        var person = new Person();
        return new InstanceBuildingResult<Person>(person);
    }
}
  • You may inherit the SimpleInstanceBuilder<T> class and implement the PrepareNewInstance method. This option should be used for really simple instance building that does not require any additional parameters being provided to the constructor. It is most suitable for complex types that have publicly exposed non-read-only members.
using TryAtSoftware.Randomizer.Core;

public class PersonInstanceBuilder : SimpleInstanceBuilder<Person>
{
    protected override Person PrepareNewInstance() => new Person();
}

Value setting phase

In this phase the SetValue method for the value setter of each registered randomization rule will be invoked. The order will be preserved - the value setter of a given randomization rule will be invoked before the value setter of a randomization rule that is registered after the given.

Best practices and recommendations

  • We do not recommend using complex randomizers with abstract classes or interfaces. While it is possible to make such a setup work, there may be some intricacies along the way. The AddRandomizationRule and OverrideRandomizationRule methods are publicly exposed so extension methods can be extracted (or even inheritance will get the job done for some simple cases). Another idea that is especially useful when dealing with many derived types that have behavioral but not structural differences, is to make the complex randomizer generic.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.2 102 3/13/2024
2.0.2-alpha.1 311 8/15/2023
2.0.1 429 6/14/2023
1.0.4 162 6/13/2023
1.0.4-alpha.4 1,030 1/31/2023
1.0.4-alpha.3 90 1/25/2023
1.0.4-alpha.2 92 1/14/2023
1.0.4-alpha.1 95 1/11/2023
1.0.3 691 3/6/2022
1.0.3-alpha.4 135 2/3/2022
1.0.3-alpha.3 116 2/3/2022
1.0.3-alpha.2 114 2/3/2022
1.0.3-alpha.1 112 2/3/2022
1.0.2 713 6/11/2021
1.0.1 307 6/11/2021