diff --git a/src/AppCoreNet.Diagnostics.Sources/Ensure.Arg.cs b/src/AppCoreNet.Diagnostics.Sources/Ensure.Arg.cs index cef1dbd..57dfa96 100644 --- a/src/AppCoreNet.Diagnostics.Sources/Ensure.Arg.cs +++ b/src/AppCoreNet.Diagnostics.Sources/Ensure.Arg.cs @@ -259,6 +259,42 @@ public static void OfType( OfType(type, typeof(TExpected), paramName); } + /// + /// Ensures that the argument is of the expected type. + /// + /// The argument. + /// The expected . + /// The parameter name. + /// The type argument is not of the expected type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [StackTraceHidden] + public static void OfType( + object? value, + Type expectedType, + [CallerArgumentExpression("value")] string? paramName = null) + { + if (value != null) + { + OfType(value.GetType(), expectedType, paramName); + } + } + + /// + /// Ensures that the argument is of the expected type. + /// + /// The expected . + /// The argument. + /// The parameter name. + /// The type argument is not of the expected type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [StackTraceHidden] + public static void OfType( + object? value, + [CallerArgumentExpression("value")] string? paramName = null) + { + OfType(value, typeof(TExpected), paramName); + } + /// /// Ensures that the type argument is of the expected type. Supports testing for /// open generic types. @@ -303,6 +339,46 @@ public static void OfGenericType( OfGenericType(type, typeof(TExpected), paramName); } + /// + /// Ensures that the argument is of the expected type. Supports testing for + /// open generic types. + /// + /// The argument. + /// The expected . + /// The parameter name. + /// The type argument is not of the expected type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [StackTraceHidden] + public static void OfGenericType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] + object? value, + Type expectedType, + [CallerArgumentExpression("value")] string? paramName = null) + { + if (value != null) + { + OfGenericType(value.GetType(), expectedType, paramName); + } + } + + /// + /// Ensures that the argument is of the expected type. Supports testing for + /// open generic types. + /// + /// The expected . + /// The argument. + /// The parameter name. + /// The type argument is not of the expected type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [StackTraceHidden] + public static void OfGenericType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] + object? value, + [CallerArgumentExpression("value")] string? paramName = null) + { + OfGenericType(value, typeof(TExpected), paramName); + } + [StackTraceHidden] private static bool IsAssignableTo( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] diff --git a/test/AppCoreNet.Diagnostics.Tests/EnsureTests.Arg.cs b/test/AppCoreNet.Diagnostics.Tests/EnsureTests.Arg.cs index 970e34b..9112fce 100644 --- a/test/AppCoreNet.Diagnostics.Tests/EnsureTests.Arg.cs +++ b/test/AppCoreNet.Diagnostics.Tests/EnsureTests.Arg.cs @@ -181,12 +181,39 @@ public void OfTypeThrowsForUnrelatedType() .Be("param"); } + [Theory] + [InlineData(typeof(IEnumerable))] + [InlineData(typeof(IEnumerable))] + [InlineData(typeof(ExpectedArgBaseType))] + [InlineData(typeof(ExpectedArgType))] + public void OfTypeDoesNotThrowForRelatedValue(Type expectedType) + { + object value = new ExpectedArgType(); + Ensure.Arg.OfType(value, expectedType, "param"); + } + + [Fact] + public void OfTypeThrowsForUnrelatedValue() + { + var exception = Assert.Throws( + () => Ensure.Arg.OfType(string.Empty, typeof(ExpectedArgType), "param")); + + exception.ParamName.Should() + .Be("param"); + } + [Fact] public void OfTypeDoesNotThrowForNullType() { Ensure.Arg.OfType(null, typeof(string)); } + [Fact] + public void OfTypeDoesNotThrowForNullValue() + { + Ensure.Arg.OfType((object?)null, typeof(string)); + } + [Theory] [InlineData(typeof(IEnumerable))] [InlineData(typeof(IEnumerable))] @@ -199,12 +226,30 @@ public void OfGenericTypeDoesNotThrowForRelatedTypes(Type expectedType) Ensure.Arg.OfGenericType(type, expectedType, "param"); } + [Theory] + [InlineData(typeof(IEnumerable))] + [InlineData(typeof(IEnumerable))] + [InlineData(typeof(IEnumerable<>))] + [InlineData(typeof(ExpectedArgBaseType))] + [InlineData(typeof(ExpectedArgType))] + public void OfGenericTypeDoesNotThrowForRelatedValue(Type expectedType) + { + object value = new ExpectedArgType(); + Ensure.Arg.OfGenericType(value, expectedType, "param"); + } + [Fact] public void OfGenericTypeDoesNotThrowForNullType() { Ensure.Arg.OfGenericType(null, typeof(string)); } + [Fact] + public void OfGenericTypeDoesNotThrowForNullValue() + { + Ensure.Arg.OfGenericType((object?)null, typeof(string)); + } + [Fact] public void OfGenericTypeThrowsForUnrelatedType() { @@ -214,5 +259,15 @@ public void OfGenericTypeThrowsForUnrelatedType() exception.ParamName.Should() .Be("param"); } + + [Fact] + public void OfGenericTypeThrowsForUnrelatedValue() + { + var exception = Assert.Throws( + () => Ensure.Arg.OfGenericType(string.Empty, typeof(ExpectedArgType), "param")); + + exception.ParamName.Should() + .Be("param"); + } } } \ No newline at end of file