Skip to content

Commit 8c2f520

Browse files
loedemanBert Loedeman
andauthored
Fixes #86 - Implement Is(Not)AssignableToType (#143)
Co-authored-by: Bert Loedeman <info@interest-it.nl>
1 parent 6667ce1 commit 8c2f520

File tree

5 files changed

+149
-0
lines changed

5 files changed

+149
-0
lines changed

src/projects/EnsureThat/Enforcers/TypeArg.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,70 @@ public Type IsNotOfType([ValidatedNotNull]Type param, Type nonExpectedType, [Inv
160160
return param;
161161
}
162162

163+
[NotNull]
164+
[ContractAnnotation("param:null => halt")]
165+
public T IsAssignableToType<T>([ValidatedNotNull]T param, Type expectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null) where T : class
166+
{
167+
Ensure.Any.IsNotNull(param, paramName, optsFn);
168+
169+
IsAssignableToType(param.GetType(), expectedType, paramName, optsFn);
170+
171+
return param;
172+
}
173+
174+
[NotNull]
175+
[ContractAnnotation("param:null => halt")]
176+
public Type IsAssignableToType([ValidatedNotNull]Type param, Type expectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)
177+
{
178+
Ensure.Any.IsNotNull(param, paramName, optsFn);
179+
Ensure.Any.IsNotNull(expectedType, nameof(expectedType));
180+
181+
#if NETSTANDARD1_1
182+
// According to: https://devblogs.microsoft.com/dotnet/porting-to-net-core/.
183+
if (!expectedType.GetTypeInfo().IsAssignableFrom(param.GetTypeInfo()))
184+
#else
185+
if (!expectedType.IsAssignableFrom(param))
186+
#endif
187+
throw Ensure.ExceptionFactory.ArgumentException(
188+
string.Format(ExceptionMessages.Types_IsAssignableToType_Failed, expectedType.FullName, param.FullName),
189+
paramName,
190+
optsFn);
191+
192+
return param;
193+
}
194+
195+
[NotNull]
196+
[ContractAnnotation("param:null => halt")]
197+
public T IsNotAssignableToType<T>([ValidatedNotNull]T param, Type nonExpectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null) where T : class
198+
{
199+
Ensure.Any.IsNotNull(param, paramName, optsFn);
200+
201+
IsNotAssignableToType(param.GetType(), nonExpectedType, paramName, optsFn);
202+
203+
return param;
204+
}
205+
206+
[NotNull]
207+
[ContractAnnotation("param:null => halt")]
208+
public Type IsNotAssignableToType([ValidatedNotNull]Type param, Type nonExpectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)
209+
{
210+
Ensure.Any.IsNotNull(param, paramName, optsFn);
211+
Ensure.Any.IsNotNull(nonExpectedType, nameof(nonExpectedType));
212+
213+
#if NETSTANDARD1_1
214+
// According to: https://devblogs.microsoft.com/dotnet/porting-to-net-core/.
215+
if (nonExpectedType.GetTypeInfo().IsAssignableFrom(param.GetTypeInfo()))
216+
#else
217+
if (nonExpectedType.IsAssignableFrom(param))
218+
#endif
219+
throw Ensure.ExceptionFactory.ArgumentException(
220+
string.Format(ExceptionMessages.Types_IsNotAssignableToType_Failed, nonExpectedType.FullName),
221+
paramName,
222+
optsFn);
223+
224+
return param;
225+
}
226+
163227
[NotNull]
164228
[ContractAnnotation("param:null => halt")]
165229
public T IsClass<T>([ValidatedNotNull]T param, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)

src/projects/EnsureThat/EnsureArg.Types.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,26 @@ public static object IsNotOfType([ValidatedNotNull]object param, Type nonExpecte
106106
public static Type IsNotOfType([ValidatedNotNull]Type param, Type nonExpectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)
107107
=> Ensure.Type.IsNotOfType(param, nonExpectedType, paramName, optsFn);
108108

109+
[NotNull]
110+
[ContractAnnotation("param:null => halt")]
111+
public static object IsAssignableToType([ValidatedNotNull] object param, Type expectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)
112+
=> Ensure.Type.IsAssignableToType(param, expectedType, paramName, optsFn);
113+
114+
[NotNull]
115+
[ContractAnnotation("param:null => halt")]
116+
public static Type IsAssignableToType([ValidatedNotNull]Type param, Type expectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)
117+
=> Ensure.Type.IsAssignableToType(param, expectedType, paramName, optsFn);
118+
119+
[NotNull]
120+
[ContractAnnotation("param:null => halt")]
121+
public static object IsNotAssignableToType([ValidatedNotNull]object param, Type nonExpectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)
122+
=> Ensure.Type.IsNotAssignableToType(param, nonExpectedType, paramName, optsFn);
123+
124+
[NotNull]
125+
[ContractAnnotation("param:null => halt")]
126+
public static Type IsNotAssignableToType([ValidatedNotNull]Type param, Type nonExpectedType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)
127+
=> Ensure.Type.IsNotAssignableToType(param, nonExpectedType, paramName, optsFn);
128+
109129
[NotNull]
110130
[ContractAnnotation("param:null => halt")]
111131
public static object IsClass([ValidatedNotNull]object param, [InvokerParameterName] string paramName = null, OptsFn optsFn = null)

src/projects/EnsureThat/EnsureThatTypeExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ public static void IsOfType(this in TypeParam param, [NotNull] Type expectedType
3535
public static void IsNotOfType(this in TypeParam param, Type expectedType)
3636
=> Ensure.Type.IsNotOfType(param.Type, expectedType, param.Name, param.OptsFn);
3737

38+
public static void IsAssignableToType(this in TypeParam param, [NotNull] Type expectedType)
39+
=> Ensure.Type.IsAssignableToType(param.Type, expectedType, param.Name, param.OptsFn);
40+
41+
public static void IsNotAssignableToType(this in TypeParam param, Type expectedType)
42+
=> Ensure.Type.IsNotAssignableToType(param.Type, expectedType, param.Name, param.OptsFn);
43+
3844
public static void IsClass<T>(this in Param<T> param)
3945
=> Ensure.Type.IsClass(param.Value, param.Name, param.OptsFn);
4046

src/projects/EnsureThat/ExceptionMessages.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public static class ExceptionMessages
4040

4141
public static string Types_IsOfType_Failed { get; } = "The param is not of expected type. Expected: '{0}'. Got: '{1}'.";
4242
public static string Types_IsNotOfType_Failed { get; } = "The param was expected to not be of the type: '{0}'. But it was.";
43+
public static string Types_IsAssignableToType_Failed { get; } = "The param is not assignable to the expected type. Expected: '{0}'. Got: '{1}'.";
44+
public static string Types_IsNotAssignableToType_Failed { get; } = "The param was expected to not be assignable to the type: '{0}'. But it was.";
4345
public static string Types_IsClass_Failed_Null { get; } = "The param was expected to be a class, but was NULL.";
4446
public static string Types_IsClass_Failed { get; } = "The param was expected to be a class, but was type of: '{0}'.";
4547

src/tests/UnitTests/EnsureTypeParamTests.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ private class Bogus { }
1010

1111
private class NonBogus { }
1212

13+
private class AssignableToNonBogus : NonBogus { }
14+
1315
private static readonly Type BogusType = typeof(Bogus);
1416

1517
private static readonly Type NonBogusType = typeof(NonBogus);
1618

19+
private static readonly Type AssignableToNonBogusType = typeof(AssignableToNonBogus);
20+
1721
[Fact]
1822
public void IsOfType_WhenNotTypeOf_ThrowsArgumentException() => AssertIsOfTypeScenario(
1923
NonBogusType, BogusType,
@@ -52,6 +56,56 @@ public void IsNotOfType_WhenIsNotTheType_It_should_not_throw() => ShouldNotThrow
5256
() => Ensure.ThatType(typeof(Bogus), ParamName).IsNotOfType(NonBogusType),
5357
() => Ensure.ThatTypeFor(new Bogus(), ParamName).IsNotOfType(NonBogusType));
5458

59+
[Fact]
60+
public void IsAssignableToType_WhenNotAssignableToType_ThrowsArgumentException() => AssertIsAssignableToTypeScenario(
61+
NonBogusType, BogusType,
62+
() => Ensure.Type.IsAssignableToType(typeof(Bogus), NonBogusType, ParamName),
63+
() => Ensure.Type.IsAssignableToType(new Bogus(), NonBogusType, ParamName),
64+
() => EnsureArg.IsAssignableToType(typeof(Bogus), NonBogusType, ParamName),
65+
() => EnsureArg.IsAssignableToType(new Bogus(), NonBogusType, ParamName),
66+
() => Ensure.ThatType(typeof(Bogus), ParamName).IsAssignableToType(NonBogusType),
67+
() => Ensure.ThatTypeFor(new Bogus(), ParamName).IsAssignableToType(NonBogusType));
68+
69+
[Fact]
70+
public void IsAssignableToType_WhenAssignableToType_It_should_not_throw() => ShouldNotThrow(
71+
() => Ensure.Type.IsAssignableToType(NonBogusType, NonBogusType, ParamName),
72+
() => Ensure.Type.IsAssignableToType(new NonBogus(), NonBogusType, ParamName),
73+
() => EnsureArg.IsAssignableToType(NonBogusType, NonBogusType, ParamName),
74+
() => EnsureArg.IsAssignableToType(new NonBogus(), NonBogusType, ParamName),
75+
() => Ensure.ThatType(typeof(NonBogus), ParamName).IsAssignableToType(NonBogusType),
76+
() => Ensure.ThatTypeFor(new NonBogus(), ParamName).IsAssignableToType(NonBogusType),
77+
() => Ensure.Type.IsAssignableToType(AssignableToNonBogusType, NonBogusType, ParamName),
78+
() => Ensure.Type.IsAssignableToType(new AssignableToNonBogus(), NonBogusType, ParamName),
79+
() => EnsureArg.IsAssignableToType(AssignableToNonBogusType, NonBogusType, ParamName),
80+
() => EnsureArg.IsAssignableToType(new AssignableToNonBogus(), NonBogusType, ParamName),
81+
() => Ensure.ThatType(typeof(AssignableToNonBogus), ParamName).IsAssignableToType(NonBogusType),
82+
() => Ensure.ThatTypeFor(new AssignableToNonBogus(), ParamName).IsAssignableToType(NonBogusType));
83+
84+
[Fact]
85+
public void IsNotAssignableToType_WhenAssignableToType_ThrowsArgumentException() => ShouldThrow<ArgumentException>(
86+
string.Format(ExceptionMessages.Types_IsNotAssignableToType_Failed, NonBogusType),
87+
() => Ensure.Type.IsNotAssignableToType(typeof(NonBogus), NonBogusType, ParamName),
88+
() => Ensure.Type.IsNotAssignableToType(new NonBogus(), NonBogusType, ParamName),
89+
() => EnsureArg.IsNotAssignableToType(typeof(NonBogus), NonBogusType, ParamName),
90+
() => EnsureArg.IsNotAssignableToType(new NonBogus(), NonBogusType, ParamName),
91+
() => Ensure.ThatType(typeof(NonBogus), ParamName).IsNotAssignableToType(NonBogusType),
92+
() => Ensure.ThatTypeFor(new NonBogus(), ParamName).IsNotAssignableToType(NonBogusType),
93+
() => Ensure.Type.IsNotAssignableToType(typeof(AssignableToNonBogus), NonBogusType, ParamName),
94+
() => Ensure.Type.IsNotAssignableToType(new AssignableToNonBogus(), NonBogusType, ParamName),
95+
() => EnsureArg.IsNotAssignableToType(typeof(AssignableToNonBogus), NonBogusType, ParamName),
96+
() => EnsureArg.IsNotAssignableToType(new AssignableToNonBogus(), NonBogusType, ParamName),
97+
() => Ensure.ThatType(typeof(AssignableToNonBogus), ParamName).IsNotAssignableToType(NonBogusType),
98+
() => Ensure.ThatTypeFor(new AssignableToNonBogus(), ParamName).IsNotAssignableToType(NonBogusType));
99+
100+
[Fact]
101+
public void IsNotAssignableToType_WhenNotAssignableToType_It_should_not_throw() => ShouldNotThrow(
102+
() => Ensure.Type.IsNotAssignableToType(BogusType, NonBogusType, ParamName),
103+
() => Ensure.Type.IsNotAssignableToType(new Bogus(), NonBogusType, ParamName),
104+
() => EnsureArg.IsNotAssignableToType(BogusType, NonBogusType, ParamName),
105+
() => EnsureArg.IsNotAssignableToType(new Bogus(), NonBogusType, ParamName),
106+
() => Ensure.ThatType(typeof(Bogus), ParamName).IsNotAssignableToType(NonBogusType),
107+
() => Ensure.ThatTypeFor(new Bogus(), ParamName).IsNotAssignableToType(NonBogusType));
108+
55109
[Fact]
56110
public void IsInt_WhenNotTypeOf_ThrowsArgumentException() => AssertIsOfTypeScenario(
57111
typeof(int), typeof(decimal),
@@ -258,6 +312,9 @@ public void IsClass_WhenIsClass_It_should_not_throw()
258312
private static void AssertIsOfTypeScenario(Type expected, Type actual, params Action[] actions)
259313
=> ShouldThrow<ArgumentException>(string.Format(ExceptionMessages.Types_IsOfType_Failed, expected.FullName, actual.FullName), actions);
260314

315+
private static void AssertIsAssignableToTypeScenario(Type expected, Type actual, params Action[] actions)
316+
=> ShouldThrow<ArgumentException>(string.Format(ExceptionMessages.Types_IsAssignableToType_Failed, expected.FullName, actual.FullName), actions);
317+
261318
private static void AssertIsNotClass(Type type, params Action[] actions)
262319
=> ShouldThrow<ArgumentException>(string.Format(ExceptionMessages.Types_IsClass_Failed, type.FullName), actions);
263320

0 commit comments

Comments
 (0)