Skip to content

Commit b4d0472

Browse files
authored
Merge pull request #19 from servicetitan/type-helper
TypeHelper class code formatting and performance improvements
2 parents 5be2094 + 971370b commit b4d0472

7 files changed

Lines changed: 689 additions & 397 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using NUnit.Framework;
4+
using Xtensive.Reflection;
5+
6+
namespace Xtensive.Orm.Tests.Core.Reflection
7+
{
8+
[TestFixture]
9+
public class TypeHelperGetGenericInterfaceTests
10+
{
11+
private class ListInt : List<int>
12+
{ }
13+
14+
private class ListIntLvl1 : ListInt
15+
{ }
16+
17+
private class GenericList<T> : List<T>
18+
{ }
19+
20+
private class GenericListLvl1<T> : GenericList<T>
21+
{ }
22+
23+
private class GenericListLvl1Int : GenericListLvl1<int>
24+
{ }
25+
26+
private class GenericListInt : GenericList<int>
27+
{ }
28+
29+
private class GenericListIntLvl1 : GenericListInt
30+
{ }
31+
32+
[Test]
33+
public void InterfaceIsDiscoverable_OnOpenGenericType() =>
34+
Assert.IsNotNull(typeof(List<>).GetGenericInterface(typeof(IList<>)));
35+
36+
[Test]
37+
public void InterfaceIsDiscoverable_OnOpenGenericInterface() =>
38+
Assert.IsNotNull(typeof(IList<>).GetGenericInterface(typeof(ICollection<>)));
39+
40+
[Test]
41+
public void InterfaceIsDiscoverable_OnClosedGenericType() =>
42+
Assert.AreSame(typeof(List<int>).GetGenericInterface(typeof(IList<>)), typeof(IList<int>));
43+
44+
[Test]
45+
public void InterfaceIsDiscoverable_OnClosedGenericInterface() =>
46+
Assert.AreSame(typeof(IList<int>).GetGenericInterface(typeof(ICollection<>)), typeof(ICollection<int>));
47+
48+
[Test]
49+
public void InterfaceIsDiscoverable_OnItself() =>
50+
Assert.AreSame(typeof(IList<int>).GetGenericInterface(typeof(IList<>)), typeof(IList<int>));
51+
52+
[TestCase(typeof(ListInt))]
53+
[TestCase(typeof(ListIntLvl1))]
54+
[TestCase(typeof(GenericList<int>))]
55+
[TestCase(typeof(GenericListLvl1<int>))]
56+
[TestCase(typeof(GenericListLvl1Int))]
57+
[TestCase(typeof(GenericListInt))]
58+
[TestCase(typeof(GenericListIntLvl1))]
59+
public void InterfaceIsDiscoverable_OnAnyAncestorOfAnImplementor(Type type) =>
60+
Assert.AreSame(type.GetGenericInterface(typeof(IList<>)), typeof(IList<int>));
61+
62+
[Test]
63+
public void NullIsReturnedIfNoMatchFound() =>
64+
Assert.IsNull(typeof(ICollection<int>).GetGenericInterface(typeof(IList<>)));
65+
66+
[Test]
67+
public void NullIsAcceptedAsFirstParameter() =>
68+
Assert.IsNull(TypeHelper.GetGenericInterface(null, typeof(List<>)));
69+
}
70+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using NUnit.Framework;
4+
using Xtensive.Reflection;
5+
6+
namespace Xtensive.Orm.Tests.Core.Reflection
7+
{
8+
[TestFixture]
9+
public class TypeHelperGetGenericTypeTests
10+
{
11+
private class ListInt : List<int>
12+
{ }
13+
14+
private class ListIntLvl1 : ListInt
15+
{ }
16+
17+
private class GenericList<T> : List<T>
18+
{ }
19+
20+
private class GenericListLvl1<T> : GenericList<T>
21+
{ }
22+
23+
private class GenericListLvl1Int : GenericListLvl1<int>
24+
{ }
25+
26+
private class GenericListInt : GenericList<int>
27+
{ }
28+
29+
private class GenericListIntLvl1 : GenericListInt
30+
{ }
31+
32+
[Test]
33+
public void ParameterizedGenericTypeIsDiscoverable_ByItself() =>
34+
Assert.AreSame(typeof(List<int>).GetGenericType(typeof(List<>)), typeof(List<int>));
35+
36+
[Test]
37+
public void ParameterizedGenericTypeIsDiscoverable_ByItsDirectNonGenericAncestor() =>
38+
Assert.AreSame(typeof(ListInt).GetGenericType(typeof(List<>)), typeof(List<int>));
39+
40+
[Test]
41+
public void ParameterizedGenericTypeIsDiscoverable_ByItsIndirectNonGenericAncestor() =>
42+
Assert.AreSame(typeof(ListIntLvl1).GetGenericType(typeof(List<>)), typeof(List<int>));
43+
44+
[Test]
45+
public void ParameterizedGenericTypeIsDiscoverable_ByItsDirectGenericAncestor() =>
46+
Assert.AreSame(typeof(GenericList<int>).GetGenericType(typeof(List<>)), typeof(List<int>));
47+
48+
[Test]
49+
public void ParameterizedGenericTypeIsDiscoverable_ByItsIndirectGenericAncestor() =>
50+
Assert.AreSame(typeof(GenericListLvl1<int>).GetGenericType(typeof(List<>)), typeof(List<int>));
51+
52+
[Test]
53+
public void ParameterizedGenericTypeIsDiscoverable_ByAnAncestorOfItsDirectGenericAncestor() =>
54+
Assert.AreSame(typeof(GenericListIntLvl1).GetGenericType(typeof(List<>)), typeof(List<int>));
55+
56+
[Test]
57+
public void ParameterizedGenericTypeIsDiscoverable_ByAnAncestorOfItsIndirectGenericAncestor() =>
58+
Assert.AreSame(typeof(GenericListLvl1Int).GetGenericType(typeof(List<>)), typeof(List<int>));
59+
60+
[Test]
61+
public void ParameterizedGenericInterfaceIsDiscoverable_ByItself() =>
62+
Assert.AreSame(typeof(IList<int>).GetGenericType(typeof(IList<>)), typeof(IList<int>));
63+
64+
[Test]
65+
public void ParameterizedGenericInterfaceIsNotDiscoverable_ByItsImplementation() =>
66+
Assert.IsNull(typeof(List<int>).GetGenericType(typeof(IList<>)));
67+
68+
[Test]
69+
public void NullIsReturnedIfNoMatchFound() =>
70+
Assert.IsNull(typeof(Stack<int>).GetGenericType(typeof(List<>)));
71+
72+
[Test]
73+
public void NullIsAcceptedAsFirstParameter() =>
74+
Assert.IsNull(TypeHelper.GetGenericType(null, typeof(List<>)));
75+
}
76+
}

Orm/Xtensive.Orm.Tests.Core/Reflection/TypeHelperTest.cs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,64 @@ public void IsNumericTest()
421421
this.GetType(),
422422
};
423423

424-
foreach (var numericType in numericTypes)
424+
foreach (var numericType in numericTypes) {
425425
Assert.IsTrue(numericType.IsNumericType());
426+
}
426427

427-
foreach (var nonNumericType in nonNumericTypes)
428+
foreach (var nonNumericType in nonNumericTypes) {
428429
Assert.IsFalse(nonNumericType.IsNumericType());
430+
}
431+
}
432+
433+
[Test]
434+
public void IsNullableTest()
435+
{
436+
var nullableTypes = new[] {
437+
typeof (Nullable<>),
438+
typeof (byte?),
439+
typeof (sbyte?),
440+
typeof (short?),
441+
typeof (ushort?),
442+
typeof (int?),
443+
typeof (uint?),
444+
typeof (long?),
445+
typeof (ulong?),
446+
typeof (float?),
447+
typeof (double?),
448+
typeof (decimal?),
449+
typeof (Guid?)
450+
};
451+
452+
var nonNullableTypes = new[] {
453+
typeof (string),
454+
typeof (char),
455+
typeof (bool),
456+
typeof (DateTime),
457+
typeof (TimeSpan),
458+
typeof (Guid),
459+
typeof (TypeCode),
460+
typeof (byte[]),
461+
typeof (Key),
462+
this.GetType()
463+
};
464+
465+
foreach (var type in nullableTypes) {
466+
Assert.IsTrue(type.IsNullable());
467+
}
468+
469+
foreach (var type in nonNullableTypes) {
470+
Assert.IsFalse(type.IsNullable());
471+
}
472+
}
473+
474+
[Test]
475+
public void GenericIsNullableTest()
476+
{
477+
Assert.IsTrue(TypeHelper.IsNullable<Guid?>());
478+
Assert.IsTrue(TypeHelper.IsNullable<int?>());
479+
480+
Assert.IsFalse(TypeHelper.IsNullable<int>());
481+
Assert.IsFalse(TypeHelper.IsNullable<string>());
429482
}
430483
}
431484
}

Orm/Xtensive.Orm/Orm/Linq/QueryHelper.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,7 @@ public static void TryAddConvarianceCast(ref Expression source, Type baseType)
184184

185185
public static Type GetSequenceElementType(Type type)
186186
{
187-
var sequenceType = type.GetGenericType(typeof (IEnumerable<>))
188-
?? type.GetInterfaces().Select(i => i.GetGenericType(typeof (IEnumerable<>))).FirstOrDefault(i => i!=null);
187+
var sequenceType = type.GetGenericInterface(typeof (IEnumerable<>));
189188
return sequenceType!=null ? sequenceType.GetGenericArguments()[0] : null;
190189
}
191190

Orm/Xtensive.Orm/Orm/Upgrade/Internals/DomainModelConverter.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,9 +463,7 @@ private static void CreateHierarchyForeignKey(TableInfo referencingTable, TableI
463463

464464
private static Type ToNullable(Type type, bool isNullable)
465465
{
466-
return isNullable && type.IsValueType && !type.IsNullable()
467-
? type.ToNullable()
468-
: type;
466+
return isNullable ? type.ToNullable() : type;
469467
}
470468

471469
private void ProcessDirectAssociation(TypeInfo ownerType, FieldInfo ownerField, TypeInfo targetType)

Orm/Xtensive.Orm/Orm/Upgrade/Internals/SqlModelConverter.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,10 @@ private StorageTypeInfo ExtractType(TableColumn column)
263263
return StorageTypeInfo.Undefined;
264264
}
265265

266-
if (column.IsNullable
267-
&& type.IsValueType
268-
&& !type.IsNullable())
266+
if (column.IsNullable) {
269267
type = type.ToNullable();
270-
268+
}
269+
271270
return new StorageTypeInfo(type, sqlValueType, column.IsNullable, sqlValueType.Length, sqlValueType.Precision, sqlValueType.Scale);
272271
}
273272

0 commit comments

Comments
 (0)