From e605051df94e58acebee7f9a0eaba4f335566a03 Mon Sep 17 00:00:00 2001
From: Matthias Gernand <mgernand@users.noreply.github.com>
Date: Sun, 26 May 2024 14:36:37 +0200
Subject: [PATCH] Removed dependencies. (#52)

---
 .../EntityTypeBuilderExtensions.cs            |   3 +-
 ...era.ValueObject.EntityFrameworkCore.csproj |   6 +-
 .../CompositeContractResolver.cs              |   3 +-
 .../Fluxera.ValueObject.JsonNet.csproj        |   2 +-
 .../JsonSerializerSettingsExtensions.cs       |   2 +
 .../BsonMapperExtensions.cs                   |   3 +-
 .../Fluxera.ValueObject.LiteDB.csproj         |   2 +-
 .../ConventionPackExtensions.cs               |   2 +
 .../Fluxera.ValueObject.MongoDB.csproj        |   2 +-
 .../JsonSerializerOptionsExtensions.cs        |   2 +
 .../Fluxera.ValueObject.csproj                |  12 +-
 src/Fluxera.ValueObject/Guard.cs              | 122 ++++++++++++++++++
 .../PrimitiveValueObject.cs                   |   4 +-
 .../PrimitiveValueObjectConverter.cs          |   3 +-
 src/Fluxera.ValueObject/PropertyAccessor.cs   |   5 +-
 src/Fluxera.ValueObject/TypeExtensions.cs     |  56 ++++++++
 16 files changed, 206 insertions(+), 23 deletions(-)
 create mode 100644 src/Fluxera.ValueObject/Guard.cs
 create mode 100644 src/Fluxera.ValueObject/TypeExtensions.cs

diff --git a/src/Fluxera.ValueObject.EntityFrameworkCore/EntityTypeBuilderExtensions.cs b/src/Fluxera.ValueObject.EntityFrameworkCore/EntityTypeBuilderExtensions.cs
index 88ea7f4..49679ca 100644
--- a/src/Fluxera.ValueObject.EntityFrameworkCore/EntityTypeBuilderExtensions.cs
+++ b/src/Fluxera.ValueObject.EntityFrameworkCore/EntityTypeBuilderExtensions.cs
@@ -4,7 +4,6 @@
 	using System.Collections.Generic;
 	using System.Linq;
 	using System.Reflection;
-	using Fluxera.Guards;
 	using JetBrains.Annotations;
 	using Microsoft.EntityFrameworkCore;
 	using Microsoft.EntityFrameworkCore.Metadata.Builders;
@@ -23,7 +22,7 @@ public static class EntityTypeBuilderExtensions
 		/// <param name="entityTypeBuilder"></param>
 		public static void UsePrimitiveValueObject(this EntityTypeBuilder entityTypeBuilder)
 		{
-			Guard.Against.Null(entityTypeBuilder);
+			Guard.ThrowIfNull(entityTypeBuilder);
 
 			IEnumerable<PropertyInfo> properties = entityTypeBuilder.Metadata
 				.ClrType
diff --git a/src/Fluxera.ValueObject.EntityFrameworkCore/Fluxera.ValueObject.EntityFrameworkCore.csproj b/src/Fluxera.ValueObject.EntityFrameworkCore/Fluxera.ValueObject.EntityFrameworkCore.csproj
index a70bf61..a08ad77 100644
--- a/src/Fluxera.ValueObject.EntityFrameworkCore/Fluxera.ValueObject.EntityFrameworkCore.csproj
+++ b/src/Fluxera.ValueObject.EntityFrameworkCore/Fluxera.ValueObject.EntityFrameworkCore.csproj
@@ -30,15 +30,15 @@
 	</ItemGroup>
 
 	<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
-		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.*" />
+		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.30" />
 	</ItemGroup>
 
 	<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
-		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.*" />
+		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.19" />
 	</ItemGroup>
 
 	<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
-		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.*" />
+		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.5" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/src/Fluxera.ValueObject.JsonNet/CompositeContractResolver.cs b/src/Fluxera.ValueObject.JsonNet/CompositeContractResolver.cs
index d8aaa9b..8ed4507 100644
--- a/src/Fluxera.ValueObject.JsonNet/CompositeContractResolver.cs
+++ b/src/Fluxera.ValueObject.JsonNet/CompositeContractResolver.cs
@@ -4,7 +4,6 @@
 	using System.Collections;
 	using System.Collections.Generic;
 	using System.Linq;
-	using Fluxera.Guards;
 	using JetBrains.Annotations;
 	using Newtonsoft.Json.Serialization;
 
@@ -42,7 +41,7 @@ IEnumerator IEnumerable.GetEnumerator()
 		/// <param name="contractResolver"></param>
 		public void Add(IContractResolver contractResolver)
 		{
-			Guard.Against.Null(contractResolver);
+			Guard.ThrowIfNull(contractResolver);
 
 			if(this.contractResolvers.Contains(this.defaultContractResolver))
 			{
diff --git a/src/Fluxera.ValueObject.JsonNet/Fluxera.ValueObject.JsonNet.csproj b/src/Fluxera.ValueObject.JsonNet/Fluxera.ValueObject.JsonNet.csproj
index 40967ab..dd42e1d 100644
--- a/src/Fluxera.ValueObject.JsonNet/Fluxera.ValueObject.JsonNet.csproj
+++ b/src/Fluxera.ValueObject.JsonNet/Fluxera.ValueObject.JsonNet.csproj
@@ -27,7 +27,7 @@
 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 		</PackageReference>
 		<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" PrivateAssets="All" />
-		<PackageReference Include="Newtonsoft.Json" Version="13.0.*" />
+		<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/src/Fluxera.ValueObject.JsonNet/JsonSerializerSettingsExtensions.cs b/src/Fluxera.ValueObject.JsonNet/JsonSerializerSettingsExtensions.cs
index 3250680..660d377 100644
--- a/src/Fluxera.ValueObject.JsonNet/JsonSerializerSettingsExtensions.cs
+++ b/src/Fluxera.ValueObject.JsonNet/JsonSerializerSettingsExtensions.cs
@@ -13,6 +13,8 @@ public static class JsonSerializerSettingsExtensions
 		/// <param name="settings"></param>
 		public static void UsePrimitiveValueObject(this JsonSerializerSettings settings)
 		{
+			Guard.ThrowIfNull(settings);
+
 			settings.ContractResolver = new CompositeContractResolver
 			{
 				new PrimitiveValueObjectContractResolver()
diff --git a/src/Fluxera.ValueObject.LiteDB/BsonMapperExtensions.cs b/src/Fluxera.ValueObject.LiteDB/BsonMapperExtensions.cs
index 5d8bf62..f4d03c9 100644
--- a/src/Fluxera.ValueObject.LiteDB/BsonMapperExtensions.cs
+++ b/src/Fluxera.ValueObject.LiteDB/BsonMapperExtensions.cs
@@ -3,7 +3,6 @@
 	using System;
 	using System.Collections.Generic;
 	using System.Linq;
-	using Fluxera.Guards;
 	using global::LiteDB;
 	using JetBrains.Annotations;
 
@@ -20,7 +19,7 @@ public static class BsonMapperExtensions
 		/// <returns></returns>
 		public static BsonMapper UsePrimitiveValueObject(this BsonMapper mapper)
 		{
-			Guard.Against.Null(mapper);
+			Guard.ThrowIfNull(mapper);
 
 			IEnumerable<Type> primitiveValueObjectTypes = AppDomain.CurrentDomain
 				.GetAssemblies()
diff --git a/src/Fluxera.ValueObject.LiteDB/Fluxera.ValueObject.LiteDB.csproj b/src/Fluxera.ValueObject.LiteDB/Fluxera.ValueObject.LiteDB.csproj
index 1e8d149..8ed4d99 100644
--- a/src/Fluxera.ValueObject.LiteDB/Fluxera.ValueObject.LiteDB.csproj
+++ b/src/Fluxera.ValueObject.LiteDB/Fluxera.ValueObject.LiteDB.csproj
@@ -27,7 +27,7 @@
 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 		</PackageReference>
 		<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" PrivateAssets="All" />
-		<PackageReference Include="LiteDB" Version="5.0.*" />
+		<PackageReference Include="LiteDB" Version="5.0.19" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/src/Fluxera.ValueObject.MongoDB/ConventionPackExtensions.cs b/src/Fluxera.ValueObject.MongoDB/ConventionPackExtensions.cs
index 77257bc..04d757e 100644
--- a/src/Fluxera.ValueObject.MongoDB/ConventionPackExtensions.cs
+++ b/src/Fluxera.ValueObject.MongoDB/ConventionPackExtensions.cs
@@ -16,6 +16,8 @@ public static class ConventionPackExtensions
 		/// <returns></returns>
 		public static ConventionPack UsePrimitiveValueObject(this ConventionPack pack)
 		{
+			Guard.ThrowIfNull(pack);
+
 			pack.Add(new PrimitiveValueObjectConvention());
 
 			return pack;
diff --git a/src/Fluxera.ValueObject.MongoDB/Fluxera.ValueObject.MongoDB.csproj b/src/Fluxera.ValueObject.MongoDB/Fluxera.ValueObject.MongoDB.csproj
index c176e14..d22d71b 100644
--- a/src/Fluxera.ValueObject.MongoDB/Fluxera.ValueObject.MongoDB.csproj
+++ b/src/Fluxera.ValueObject.MongoDB/Fluxera.ValueObject.MongoDB.csproj
@@ -27,7 +27,7 @@
 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 		</PackageReference>
 		<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" PrivateAssets="All" />
-		<PackageReference Include="MongoDB.Driver" Version="2.25.*" />
+		<PackageReference Include="MongoDB.Driver" Version="2.25.0" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/src/Fluxera.ValueObject.SystemTextJson/JsonSerializerOptionsExtensions.cs b/src/Fluxera.ValueObject.SystemTextJson/JsonSerializerOptionsExtensions.cs
index 5e53040..5d0a925 100644
--- a/src/Fluxera.ValueObject.SystemTextJson/JsonSerializerOptionsExtensions.cs
+++ b/src/Fluxera.ValueObject.SystemTextJson/JsonSerializerOptionsExtensions.cs
@@ -15,6 +15,8 @@ public static class JsonSerializerOptionsExtensions
 		/// <param name="options"></param>
 		public static void UsePrimitiveValueObject(this JsonSerializerOptions options)
 		{
+			Guard.ThrowIfNull(options);
+
 			options.Converters.Add(new PrimitiveValueObjectJsonConverterFactory());
 		}
 	}
diff --git a/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj b/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj
index c066861..27cb483 100644
--- a/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj
+++ b/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
 	<PropertyGroup>
 		<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
@@ -22,8 +22,14 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<PackageReference Include="Fluxera.Guards" Version="8.0.*" />
-		<PackageReference Include="Fluxera.Utilities" Version="8.0.*" />
+		<InternalsVisibleTo Include="Fluxera.ValueObject.EntityFrameworkCore" />
+		<InternalsVisibleTo Include="Fluxera.ValueObject.JsonNet" />
+		<InternalsVisibleTo Include="Fluxera.ValueObject.LiteDB" />
+		<InternalsVisibleTo Include="Fluxera.ValueObject.MongoDB" />
+		<InternalsVisibleTo Include="Fluxera.ValueObject.SystemTextJson" />
+	</ItemGroup>
+
+	<ItemGroup>
 		<PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
 		  <PrivateAssets>all</PrivateAssets>
 		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
diff --git a/src/Fluxera.ValueObject/Guard.cs b/src/Fluxera.ValueObject/Guard.cs
new file mode 100644
index 0000000..e132e39
--- /dev/null
+++ b/src/Fluxera.ValueObject/Guard.cs
@@ -0,0 +1,122 @@
+namespace Fluxera.ValueObject
+{
+	using JetBrains.Annotations;
+	using System;
+	using System.Collections.Generic;
+	using System.Linq;
+	using System.Numerics;
+	using System.Runtime.CompilerServices;
+
+	internal static class Guard
+	{
+		public static T ThrowIfNull<T>(T argument, [InvokerParameterName] [CallerArgumentExpression(nameof(argument))] string parameterName = null)
+		{
+			ArgumentNullException.ThrowIfNull(argument, parameterName);
+
+			return argument;
+		}
+
+		public static string ThrowIfNullOrEmpty(string argument, [InvokerParameterName][CallerArgumentExpression(nameof(argument))] string parameterName = null)
+		{
+			argument = ThrowIfNull(argument, parameterName);
+
+			if(string.IsNullOrEmpty(argument))
+			{
+				throw new ArgumentException("Value cannot be empty.", parameterName);
+			}
+
+			return argument;
+		}
+
+		public static string ThrowIfNullOrWhiteSpace(string argument, [InvokerParameterName][CallerArgumentExpression("argument")] string parameterName = null)
+		{
+			argument = ThrowIfNull(argument, parameterName);
+
+			if(string.IsNullOrWhiteSpace(argument))
+			{
+				throw new ArgumentException("Value cannot be whitespace-only.", parameterName);
+			}
+
+			return argument;
+		}
+
+		public static bool ThrowIfFalse(bool argument, [InvokerParameterName][CallerArgumentExpression(nameof(argument))] string parameterName = null, string message = null)
+		{
+			if(!argument)
+			{
+				throw new ArgumentException(message ?? "Value cannot be false.", parameterName);
+			}
+
+			return true;
+		}
+
+		public static IEnumerable<T> ThrowIfNullOrEmpty<T>(IEnumerable<T> argument, [InvokerParameterName][CallerArgumentExpression(nameof(argument))] string parameterName = null)
+		{
+			argument = ThrowIfNull(argument, parameterName);
+
+			// ReSharper disable PossibleMultipleEnumeration
+			if(!argument.Any())
+			{
+				throw new ArgumentException("Enumerable cannot be empty.", parameterName);
+			}
+
+			return argument;
+			// ReSharper enable PossibleMultipleEnumeration
+		}
+
+#if NET7_0_OR_GREATER
+		public static T ThrowIfNegative<T>(T argument, [InvokerParameterName] [CallerArgumentExpression(nameof(argument))] string parameterName = null)
+			where T : INumber<T>
+		{
+			if(T.IsNegative(argument))
+			{
+				throw new ArgumentException("Value cannot be negative.", parameterName);
+			}
+
+			return argument;
+		}
+#endif
+
+#if NET6_0
+		public static byte ThrowIfNegative(byte argument, [InvokerParameterName][CallerArgumentExpression(nameof(argument))] string parameterName = null)
+		{
+			if(argument < 0)
+			{
+				throw new ArgumentException("Value cannot be negative.", parameterName);
+			}
+
+			return argument;
+		}
+
+		public static short ThrowIfNegative(short argument, [InvokerParameterName][CallerArgumentExpression(nameof(argument))] string parameterName = null)
+		{
+			if(argument < 0)
+			{
+				throw new ArgumentException("Value cannot be negative.", parameterName);
+			}
+
+			return argument;
+		}
+
+		public static int ThrowIfNegative(int argument, [InvokerParameterName] [CallerArgumentExpression(nameof(argument))] string parameterName = null)
+		{
+			if(argument < 0)
+			{
+				throw new ArgumentException("Value cannot be negative.", parameterName);
+			}
+
+			return argument;
+		}
+
+		public static long ThrowIfNegative(long argument, [InvokerParameterName][CallerArgumentExpression(nameof(argument))] string parameterName = null)
+		{
+			if(argument < 0)
+			{
+				throw new ArgumentException("Value cannot be negative.", parameterName);
+			}
+
+			return argument;
+		}
+#endif
+	}
+}
diff --git a/src/Fluxera.ValueObject/PrimitiveValueObject.cs b/src/Fluxera.ValueObject/PrimitiveValueObject.cs
index 0234ad5..60a65e8 100644
--- a/src/Fluxera.ValueObject/PrimitiveValueObject.cs
+++ b/src/Fluxera.ValueObject/PrimitiveValueObject.cs
@@ -3,8 +3,6 @@
 	using System;
 	using System.Collections.Generic;
 	using System.ComponentModel;
-	using Fluxera.Guards;
-	using Fluxera.Utilities.Extensions;
 	using JetBrains.Annotations;
 
 	/// <summary>
@@ -29,7 +27,7 @@ static PrimitiveValueObject()
 			Type valueType = typeof(TValue);
 			bool isPrimitive = valueType.IsPrimitive(true);
 
-			Guard.Against.False(isPrimitive, nameof(Value), "The value of a primitive value object must be a primitive, string or enum value.");
+			Guard.ThrowIfFalse(isPrimitive, nameof(Value), "The value of a primitive value object must be a primitive, string or enum value.");
 		}
 
 		/// <summary>
diff --git a/src/Fluxera.ValueObject/PrimitiveValueObjectConverter.cs b/src/Fluxera.ValueObject/PrimitiveValueObjectConverter.cs
index b02ea52..c420b1a 100644
--- a/src/Fluxera.ValueObject/PrimitiveValueObjectConverter.cs
+++ b/src/Fluxera.ValueObject/PrimitiveValueObjectConverter.cs
@@ -4,7 +4,6 @@
 	using System.Collections.Concurrent;
 	using System.ComponentModel;
 	using System.Globalization;
-	using Fluxera.Guards;
 
 	internal sealed class PrimitiveValueObjectConverter : TypeConverter
 	{
@@ -106,7 +105,7 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
 		/// <inheritdoc />
 		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
 		{
-			Guard.Against.Null(value);
+			Guard.ThrowIfNull(value);
 
 			PrimitiveValueObject<TValueObject, TValue> primitiveValueObject = (PrimitiveValueObject<TValueObject, TValue>)value;
 
diff --git a/src/Fluxera.ValueObject/PropertyAccessor.cs b/src/Fluxera.ValueObject/PropertyAccessor.cs
index 5a7eab2..d28aa38 100644
--- a/src/Fluxera.ValueObject/PropertyAccessor.cs
+++ b/src/Fluxera.ValueObject/PropertyAccessor.cs
@@ -4,7 +4,6 @@
 	using System.Collections.Concurrent;
 	using System.Linq;
 	using System.Reflection;
-	using Fluxera.Guards;
 	using JetBrains.Annotations;
 
 	[PublicAPI]
@@ -16,8 +15,8 @@ internal sealed class PropertyAccessor
 
 		private PropertyAccessor(string propertyName, Func<object, object> getterFunc)
 		{
-			Guard.Against.NullOrWhiteSpace(propertyName, nameof(propertyName));
-			Guard.Against.Null(getterFunc, nameof(getterFunc));
+			Guard.ThrowIfNullOrWhiteSpace(propertyName);
+			Guard.ThrowIfNull(getterFunc);
 
 			this.PropertyName = propertyName;
 			this.GetterFunc = getterFunc;
diff --git a/src/Fluxera.ValueObject/TypeExtensions.cs b/src/Fluxera.ValueObject/TypeExtensions.cs
new file mode 100644
index 0000000..8ae2f10
--- /dev/null
+++ b/src/Fluxera.ValueObject/TypeExtensions.cs
@@ -0,0 +1,56 @@
+namespace Fluxera.ValueObject
+{
+	using System;
+	using System.Collections.Generic;
+
+	internal static class TypeExtensions
+	{
+		private static readonly HashSet<Type> ExtraPrimitiveTypes =
+		[
+			typeof(string),
+			typeof(decimal),
+			typeof(DateOnly),
+			typeof(TimeOnly),
+			typeof(DateTime),
+			typeof(DateTimeOffset),
+			typeof(TimeSpan),
+			typeof(Guid)
+		];
+
+		/// <summary>
+		///     Determines whether the specified type is a primitive. It automatically
+		///     unwraps the wrapped type of the nullable.
+		/// </summary>
+		/// <param name="type">The type.</param>
+		/// <param name="includeEnums">If set to <c>true</c> include enums.</param>
+		/// <returns>
+		///     <c>true</c> if the specified type is a primitive; otherwise, <c>false</c>.
+		/// </returns>
+		public static bool IsPrimitive(this Type type, bool includeEnums = false)
+		{
+			type = type.UnwrapNullableType();
+
+			if(type.IsPrimitive)
+			{
+				return true;
+			}
+
+			if(includeEnums && type.IsEnum)
+			{
+				return true;
+			}
+
+			return ExtraPrimitiveTypes.Contains(type);
+		}
+
+		/// <summary>
+		///     Gets the type without nullable if the type is a <see cref="Nullable{T}" />.
+		/// </summary>
+		/// <param name="type">The type.</param>
+		/// <returns></returns>
+		private static Type UnwrapNullableType(this Type type)
+		{
+			return Nullable.GetUnderlyingType(type) ?? type;
+		}
+	}
+}