Skip to content

Commit

Permalink
Merge pull request #6 from maiconheck/feature/EF-CreateInstance-overload
Browse files Browse the repository at this point in the history
feature(Krafted.ValueObjects): `ActivatorHelperTest.CreateInstance()` method overloaded
  • Loading branch information
maiconheck authored Oct 22, 2023
2 parents d4b3f42 + fbf2606 commit 23e8dee
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 15 deletions.
3 changes: 0 additions & 3 deletions docfx_project/filterConfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,3 @@ apiRules:
- exclude:
uidRegex: ^Krafted\.Net\.Network
type: Type
- exclude:
uidRegex: ^Krafted\.ValueObjects\.Br
type: Type
4 changes: 2 additions & 2 deletions src/Krafted/Directory.build.props
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<Authors>Maicon Heck</Authors>
<Version>5.0.0-rc.2</Version>
<PackageVersion>5.0.0-rc.2</PackageVersion>
<Version>5.0.0-rc.3</Version>
<PackageVersion>5.0.0-rc.3</PackageVersion>
<Product>Krafted</Product>
<ProductName>Krafted</ProductName>
<PackageId>$(MSBuildProjectName)</PackageId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Krafted.ValueObjects;
using Krafted.ValueObjects.Pt;
using Xunit;
Expand Down Expand Up @@ -33,5 +34,30 @@ public void CreateInstance_NotEmptyNif_InstanceCreated(string notEmptyNif)
Assert.Equal(notEmptyNif, nif.Value);
});
}

[Fact]
public void CreateInstance_DefaultDateOfBirth_InstanceCreated()
{
var defaultDateOfBirth = default(DateTime);

Assert.DoesNotThrows(() =>
{
var dateOfBirth = ActivatorHelper.CreateInstance<DateOfBirthDummy>(defaultDateOfBirth);
Assert.NotNull(dateOfBirth);
});
}

[Fact]
public void CreateInstance_NotDefaultDateOfBirth_InstanceCreated()
{
var notDefaultDateOfBirth = new DateTime(1990, 10, 20);

Assert.DoesNotThrows(() =>
{
var dateOfBirth = ActivatorHelper.CreateInstance<DateOfBirthDummy>(notDefaultDateOfBirth);
Assert.NotNull(dateOfBirth);
Assert.Equal(notDefaultDateOfBirth, dateOfBirth.Value);
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Krafted.Guards;
using Krafted.ValueObjects;

namespace Krafted.UnitTest.Krafted.ValueObjects;

public sealed class DateOfBirthDummy : ValueObject<DateTime>
{
public DateOfBirthDummy(DateTime value)
{
Guard.Against.True(_ => value >= DateTime.Today, $"Invalid date of birth: {value.ToShortDateString()}.");
Value = value;
}

// Required for the ORM.
[ExcludeFromCodeCoverage]
private DateOfBirthDummy()
{
}

public static explicit operator DateOfBirthDummy(in DateTime value) => new(value);

public static DateOfBirthDummy NewDateBirth(in DateTime value) => new(value);
}
48 changes: 40 additions & 8 deletions src/Krafted/Krafted.ValueObjects/ActivatorHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,59 @@ namespace Krafted.ValueObjects
/// </para>
/// <para>
/// The CreateInstance method checks if the value is null or empty, and if it is, it creates the instance through the private constructor via reflection,
/// thus avoiding the exception.
/// Otherwise, create the instance through the public constructor.
/// to bypass the Guard Clauses, thus avoiding an exception.
/// Otherwise, it create the instance through the public constructor.
/// </para>
/// <para>The value will only be null when the EF does the mapping and starts to materialize the entity,
/// because at that time the value has not yet been loaded.</para>
/// because at that time the value has not yet been loaded.
/// </para>
/// </remarks>
public static class ActivatorHelper
{
/// <summary>
/// Creates a new instance of a Value Object for EF mapping.
/// Creates a new instance of a Value Object for EF mapping when using Entity Framework with Lazy Loading.
/// <para>
/// This method checks if the value is null or empty, and if it is, it creates the instance through the private constructor via reflection,
/// to bypass the Guard Clauses, thus avoiding an exception.
/// Otherwise, it create the instance through the public constructor.
/// </para>
/// <para>The value will only be null when the EF does the mapping and starts to materialize the entity,
/// because at that time the value has not yet been loaded.
/// </para>
/// </summary>
/// <typeparam name="TValueObject">The type.</typeparam>
/// <typeparam name="TValueObject">The type of the Value Object.</typeparam>
/// <param name="value">The value.</param>
/// <returns>The new instance of the Value Object.</returns>
/// <returns>A new instance of the Value Object.</returns>
public static TValueObject CreateInstance<TValueObject>(string value)
{
var type = typeof(TValueObject);

return !string.IsNullOrEmpty(value)
? (TValueObject)Activator.CreateInstance(type, value)! // public contructor
: (TValueObject)Activator.CreateInstance(type, nonPublic: true)!; // private contructor
? (TValueObject)Activator.CreateInstance(type, value)! // public constructor
: (TValueObject)Activator.CreateInstance(type, nonPublic: true)!; // private constructor
}

/// <summary>
/// Creates a new instance of a Value Object for EF mapping when using Entity Framework with Lazy Loading.
/// <para>
/// This method checks if the value is the DateTime default, and if it is, it creates the instance through the private constructor via reflection,
/// to bypass the Guard Clauses, thus avoiding an exception.
/// Otherwise, it create the instance through the public constructor.
/// </para>
/// <para>The value will only be the DateTime default when the EF does the mapping and starts to materialize the entity,
/// because at that time the value has not yet been loaded.
/// </para>
/// </summary>
/// <typeparam name="TValueObject">The type of the Value Object.</typeparam>
/// <param name="value">The value.</param>
/// <returns>A new instance of the Value Object.</returns>
public static TValueObject CreateInstance<TValueObject>(DateTime value)
{
var type = typeof(TValueObject);

return value != default
? (TValueObject)Activator.CreateInstance(type, value)! // public constructor
: (TValueObject)Activator.CreateInstance(type, nonPublic: true)!; // private constructor
}
}
}
4 changes: 2 additions & 2 deletions src/Krafted/Krafted.ValueObjects/Pt/Nif.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ private Nif()
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Nif(string value) => new Nif(value);
public static explicit operator Nif(string value) => new(value);

/// <summary>
/// Initializes a new instance of the <see cref="Nif"/> class.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>A new instance of the <see cref="Nif"/> class.</returns>
public static Nif NewNif(string value) => new Nif(value);
public static Nif NewNif(string value) => new(value);
}
}

0 comments on commit 23e8dee

Please sign in to comment.