Skip to content

Commit 90c2432

Browse files
author
Bart Koelman
committed
Cleanup around type helpers
1 parent ca79de7 commit 90c2432

File tree

16 files changed

+68
-122
lines changed

16 files changed

+68
-122
lines changed

src/Examples/JsonApiDotNetCoreExample/Models/Article.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public sealed class Article : Identifiable
2020

2121
[NotMapped]
2222
[HasManyThrough(nameof(IdentifiableArticleTags))]
23-
public ISet<Tag> IdentifiableTags { get; set; }
24-
public ISet<IdentifiableArticleTag> IdentifiableArticleTags { get; set; }
23+
public ICollection<Tag> IdentifiableTags { get; set; }
24+
public ICollection<IdentifiableArticleTag> IdentifiableArticleTags { get; set; }
2525
}
2626
}

src/JsonApiDotNetCore/Builders/ResourceGraphBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public IResourceGraphBuilder AddResource(Type resourceType, Type idType = null,
5757
{
5858
if (_resources.All(e => e.ResourceType != resourceType))
5959
{
60-
if (resourceType.Implements<IIdentifiable>())
60+
if (resourceType.IsOrImplementsInterface(typeof(IIdentifiable)))
6161
{
6262
pluralizedTypeName ??= FormatResourceName(resourceType);
6363
idType ??= TypeLocator.GetIdType(resourceType);
@@ -182,7 +182,7 @@ private static Type TryGetThroughType(PropertyInfo throughProperty)
182182
if (typeArguments.Length == 1)
183183
{
184184
var constructedThroughType = typeof(ICollection<>).MakeGenericType(typeArguments[0]);
185-
if (throughProperty.PropertyType.Implements(constructedThroughType))
185+
if (throughProperty.PropertyType.IsOrImplementsInterface(constructedThroughType))
186186
{
187187
return typeArguments[0];
188188
}

src/JsonApiDotNetCore/Data/DefaultResourceRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ private bool IsHasOneRelationship(string internalRelationshipName, Type type)
159159
}
160160
// relationshipAttr is null when we don't put a [RelationshipAttribute] on the inverse navigation property.
161161
// In this case we use reflection to figure out what kind of relationship is pointing back.
162-
return !type.GetProperty(internalRelationshipName).PropertyType.Inherits(typeof(IEnumerable));
162+
return !type.GetProperty(internalRelationshipName).PropertyType.IsOrImplementsInterface(typeof(IEnumerable));
163163
}
164164

165165
private void DetachRelationships(TResource entity)

src/JsonApiDotNetCore/Extensions/QueryableExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,10 @@ private static IQueryable<TSource> CallGenericWhereContainsMethod<TSource>(IQuer
206206
member = Expression.Property(entity, filter.Attribute.PropertyInfo.Name);
207207

208208
var method = ContainsMethod.MakeGenericMethod(member.Type);
209-
210-
var list = TypeHelper.CreateListFor(member.Type);
209+
210+
var listType = typeof(List<>).MakeGenericType(member.Type);
211+
var list = (IList)TypeHelper.CreateInstance(listType);
212+
211213
foreach (var value in propertyValues)
212214
{
213215
object targetType;

src/JsonApiDotNetCore/Extensions/TypeExtensions.cs

Lines changed: 13 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ internal static class TypeExtensions
1616
/// ((IList)myList).CopyToList(targetType).
1717
/// </code>
1818
/// </summary>
19-
public static IList CopyToList(this IEnumerable source, Type type)
19+
public static IList CopyToList(this IEnumerable copyFrom, Type elementType)
2020
{
21-
Type collectionType = typeof(List<>).MakeGenericType(type);
22-
return (IList)CopyToTypedCollection(source, collectionType);
21+
Type collectionType = typeof(List<>).MakeGenericType(elementType);
22+
return (IList)CopyToTypedCollection(copyFrom, collectionType);
2323
}
2424

2525
/// <summary>
@@ -34,7 +34,7 @@ public static IEnumerable CopyToTypedCollection(this IEnumerable source, Type co
3434
if (collectionType == null) throw new ArgumentNullException(nameof(collectionType));
3535

3636
var concreteCollectionType = collectionType.ToConcreteCollectionType();
37-
dynamic concreteCollectionInstance = concreteCollectionType.New<dynamic>();
37+
dynamic concreteCollectionInstance = TypeHelper.CreateInstance(concreteCollectionType);
3838

3939
foreach (var item in source)
4040
{
@@ -44,80 +44,29 @@ public static IEnumerable CopyToTypedCollection(this IEnumerable source, Type co
4444
return concreteCollectionInstance;
4545
}
4646

47-
/// <summary>
48-
/// Creates a List{TInterface} where TInterface is the generic for type specified by t
49-
/// </summary>
50-
public static IEnumerable GetEmptyCollection(this Type t)
51-
{
52-
if (t == null) throw new ArgumentNullException(nameof(t));
53-
54-
var listType = typeof(List<>).MakeGenericType(t);
55-
var list = (IEnumerable)CreateNewInstance(listType);
56-
return list;
57-
}
58-
5947
public static string GetResourceStringId<TResource, TId>(TId id) where TResource : class, IIdentifiable<TId>
6048
{
61-
var tempResource = typeof(TResource).New<TResource>();
49+
var tempResource = TypeHelper.CreateInstance<TResource>();
6250
tempResource.Id = id;
6351
return tempResource.StringId;
6452
}
6553

66-
public static object New(this Type t)
67-
{
68-
return New<object>(t);
69-
}
70-
7154
/// <summary>
72-
/// Creates a new instance of type t, casting it to the specified type.
55+
/// Whether the specified source type implements or equals the specified interface.
7356
/// </summary>
74-
public static T New<T>(this Type t)
57+
public static bool IsOrImplementsInterface(this Type source, Type interfaceType)
7558
{
76-
if (t == null) throw new ArgumentNullException(nameof(t));
77-
78-
var instance = (T)CreateNewInstance(t);
79-
return instance;
80-
}
81-
82-
private static object CreateNewInstance(Type type)
83-
{
84-
try
59+
if (interfaceType == null)
8560
{
86-
return Activator.CreateInstance(type);
61+
throw new ArgumentNullException(nameof(interfaceType));
8762
}
88-
catch (Exception exception)
63+
64+
if (source == null)
8965
{
90-
throw new InvalidOperationException($"Failed to create an instance of '{type.FullName}' using its default constructor.", exception);
66+
return false;
9167
}
92-
}
93-
94-
/// <summary>
95-
/// Whether or not a type implements an interface.
96-
/// </summary>
97-
public static bool Implements<T>(this Type concreteType)
98-
=> Implements(concreteType, typeof(T));
99-
100-
/// <summary>
101-
/// Whether or not a type implements an interface.
102-
/// </summary>
103-
public static bool Implements(this Type concreteType, Type interfaceType)
104-
=> interfaceType?.IsAssignableFrom(concreteType) == true;
10568

106-
/// <summary>
107-
/// Whether or not a type inherits a base type.
108-
/// </summary>
109-
public static bool Inherits<T>(this Type concreteType)
110-
=> Inherits(concreteType, typeof(T));
111-
112-
/// <summary>
113-
/// Whether or not a type inherits a base type.
114-
/// </summary>
115-
public static bool Inherits(this Type concreteType, Type interfaceType)
116-
=> interfaceType?.IsAssignableFrom(concreteType) == true;
117-
118-
public static bool ImplementsInterface(this Type source, Type interfaceType)
119-
{
120-
return source.GetInterfaces().Any(type => type == interfaceType);
69+
return source == interfaceType || source.GetInterfaces().Any(type => type == interfaceType);
12170
}
12271
}
12372
}

src/JsonApiDotNetCore/Graph/TypeLocator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static Type GetIdType(Type resourceType)
2929
/// </returns>
3030
internal static bool TryGetResourceDescriptor(Type type, out ResourceDescriptor descriptor)
3131
{
32-
if (type.Implements<IIdentifiable>())
32+
if (type.IsOrImplementsInterface(typeof(IIdentifiable)))
3333
{
3434
descriptor = new ResourceDescriptor(type, GetIdType(type));
3535
return true;

src/JsonApiDotNetCore/Hooks/Execution/DiffableEntityHashSet.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ public IEnumerable<EntityDiffPair<TResource>> GetDiffs()
7575
{
7676
var propertyInfo = TypeHelper.ParseNavigationExpression(navigationAction);
7777
var propertyType = propertyInfo.PropertyType;
78-
if (propertyType.ImplementsInterface(typeof(IEnumerable)))
78+
if (propertyType.IsOrImplementsInterface(typeof(IEnumerable)))
7979
{
8080
propertyType = TypeHelper.TryGetCollectionElementType(propertyType);
8181
}
8282

83-
if (propertyType.Implements<IIdentifiable>())
83+
if (propertyType.IsOrImplementsInterface(typeof(IIdentifiable)))
8484
{
8585
// the navigation action references a relationship. Redirect the call to the relationship dictionary.
8686
return base.GetAffected(navigationAction);

src/JsonApiDotNetCore/Hooks/Traversal/TraversalHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ private HashSet<TResource> UniqueInTree<TResource>(IEnumerable<TResource> entiti
264264
/// <param name="attr">Relationship attribute</param>
265265
private RightType GetRightTypeFromRelationship(RelationshipAttribute attr)
266266
{
267-
if (attr is HasManyThroughAttribute throughAttr && throughAttr.ThroughType.Inherits(typeof(IIdentifiable)))
267+
if (attr is HasManyThroughAttribute throughAttr && throughAttr.ThroughType.IsOrImplementsInterface(typeof(IIdentifiable)))
268268
{
269269
return throughAttr.ThroughType;
270270
}

src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,14 @@ private Type GetResourceTypeFromController(Type type)
128128
var controllerBase = typeof(ControllerBase);
129129
var jsonApiMixin = typeof(JsonApiControllerMixin);
130130
var target = typeof(BaseJsonApiController<,>);
131-
var identifiable = typeof(IIdentifiable);
132131
var currentBaseType = type;
133132
while (!currentBaseType.IsGenericType || currentBaseType.GetGenericTypeDefinition() != target)
134133
{
135134
var nextBaseType = currentBaseType.BaseType;
136135

137136
if ( (nextBaseType == controllerBase || nextBaseType == jsonApiMixin) && currentBaseType.IsGenericType)
138137
{
139-
var potentialResource = currentBaseType.GetGenericArguments().FirstOrDefault(t => t.Inherits(identifiable));
138+
var potentialResource = currentBaseType.GetGenericArguments().FirstOrDefault(t => t.IsOrImplementsInterface(typeof(IIdentifiable)));
140139
if (potentialResource != null)
141140
{
142141
return potentialResource;

src/JsonApiDotNetCore/Internal/Generics/RepositoryRelationshipUpdateHelper.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ private async Task UpdateOneToManyAsync(IIdentifiable parent, RelationshipAttrib
7474
if (!relationshipIds.Any())
7575
{
7676
var collectionType = relationship.PropertyInfo.PropertyType.ToConcreteCollectionType();
77-
value = collectionType.New<IEnumerable>();
77+
value = (IEnumerable)TypeHelper.CreateInstance(collectionType);
7878
}
7979
else
8080
{
@@ -123,7 +123,7 @@ private async Task UpdateManyToManyAsync(IIdentifiable parent, HasManyThroughAtt
123123

124124
var newLinks = relationshipIds.Select(x =>
125125
{
126-
var link = relationship.ThroughType.New();
126+
var link = TypeHelper.CreateInstance(relationship.ThroughType);
127127
relationship.LeftIdProperty.SetValue(link, TypeHelper.ConvertType(parentId, relationship.LeftIdProperty.PropertyType));
128128
relationship.RightIdProperty.SetValue(link, TypeHelper.ConvertType(x, relationship.RightIdProperty.PropertyType));
129129
return link;

0 commit comments

Comments
 (0)