Skip to content

Commit 7a33bc5

Browse files
LuukN2commonsensesoftware
authored andcommitted
Support substitution of types with circular references.
Replaced tuple with PropertyDependency.
1 parent 089a06f commit 7a33bc5

File tree

2 files changed

+31
-18
lines changed

2 files changed

+31
-18
lines changed

src/Common.OData.ApiExplorer/AspNet.OData/DefaultModelTypeBuilder.cs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public sealed class DefaultModelTypeBuilder : IModelTypeBuilder
2929
static readonly Type IEnumerableOfT = typeof( IEnumerable<> );
3030
readonly ICollection<Assembly> assemblies;
3131
readonly ConcurrentDictionary<ApiVersion, ModuleBuilder> modules = new ConcurrentDictionary<ApiVersion, ModuleBuilder>();
32-
readonly ConcurrentDictionary<EdmTypeKey, Type> generatedEdmTypes = new ConcurrentDictionary<EdmTypeKey, Type>();
32+
readonly ConcurrentDictionary<EdmTypeKey, TypeInfo> generatedEdmTypes = new ConcurrentDictionary<EdmTypeKey, TypeInfo>();
3333
readonly ConcurrentDictionary<EdmTypeKey, TypeBuilder> unfinishedTypes = new ConcurrentDictionary<EdmTypeKey, TypeBuilder>();
3434
readonly HashSet<EdmTypeKey> visitedEdmTypes = new HashSet<EdmTypeKey>();
3535
readonly Dictionary<EdmTypeKey, List<PropertyDependency>> dependencies = new Dictionary<EdmTypeKey, List<PropertyDependency>>();
@@ -67,7 +67,7 @@ public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType,
6767
var structuralProperties = structuredType.Properties().ToDictionary( p => p.Name, StringComparer.OrdinalIgnoreCase );
6868
var clrTypeMatchesEdmType = true;
6969
var hasUnfinishedTypes = false;
70-
var dependentProperties = new List<Tuple<EdmTypeKey, bool, string>>();
70+
var dependentProperties = new List<PropertyDependency>();
7171

7272
foreach ( var property in clrType.GetProperties( bindingFlags ) )
7373
{
@@ -98,8 +98,8 @@ public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType,
9898
{
9999
clrTypeMatchesEdmType = false;
100100
hasUnfinishedTypes = true;
101-
var dependencyTuple = new Tuple<EdmTypeKey, bool, string>( elementKey, true, property.Name );
102-
dependentProperties.Add( dependencyTuple );
101+
var dependency = new PropertyDependency( elementKey, true, property.Name );
102+
dependentProperties.Add( dependency );
103103
continue;
104104
}
105105

@@ -130,8 +130,8 @@ public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType,
130130
{
131131
clrTypeMatchesEdmType = false;
132132
hasUnfinishedTypes = true;
133-
var dependencyTuple = new Tuple<EdmTypeKey, bool, string>( propertyTypeKey, false, property.Name );
134-
dependentProperties.Add( dependencyTuple );
133+
var dependency = new PropertyDependency( propertyTypeKey, false, property.Name );
134+
dependentProperties.Add( dependency );
135135
continue;
136136
}
137137
}
@@ -152,15 +152,14 @@ public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType,
152152
if ( !unfinishedTypes.TryGetValue( typeKey, out var typeBuilder ) )
153153
{
154154
typeBuilder = CreateTypeBuilderFromSignature( signature );
155-
var newPropertyDependencies = new List<PropertyDependency>();
156-
foreach ( var dependencyTuple in dependentProperties )
155+
156+
foreach ( var propertyDependency in dependentProperties )
157157
{
158-
newPropertyDependencies.Add( new PropertyDependency( typeBuilder, dependencyTuple.Item1, dependencyTuple.Item2, dependencyTuple.Item3 ) );
158+
propertyDependency.DependentType = typeBuilder;
159159
}
160160

161-
dependencies.Add( typeKey, newPropertyDependencies );
162-
unfinishedTypes.GetOrAdd( typeKey, typeBuilder );
163-
161+
dependencies.Add( typeKey, dependentProperties );
162+
ResolveForUnfinishedTypes();
164163
return ResolveDependencies( typeBuilder, typeKey );
165164
}
166165

@@ -218,6 +217,7 @@ TypeBuilder CreateTypeBuilderFromSignature( ClassSignature @class )
218217
private Type ResolveDependencies( TypeBuilder typeBuilder, EdmTypeKey typeKey )
219218
{
220219
var keys = dependencies.Keys.ToList();
220+
unfinishedTypes.GetOrAdd( typeKey, typeBuilder );
221221

222222
foreach ( var key in keys )
223223
{
@@ -255,11 +255,27 @@ private Type ResolveDependencies( TypeBuilder typeBuilder, EdmTypeKey typeKey )
255255
}
256256
}
257257
}
258+
259+
if ( !dependencies.ContainsKey( typeKey ) )
260+
{
261+
var typeInfo = typeBuilder.CreateTypeInfo();
262+
generatedEdmTypes.GetOrAdd( key, typeInfo );
263+
return typeBuilder.CreateTypeInfo();
264+
}
258265
}
259266

260267
return typeBuilder;
261268
}
262269

270+
private void ResolveForUnfinishedTypes()
271+
{
272+
var keys = unfinishedTypes.Keys;
273+
foreach ( var key in keys )
274+
{
275+
ResolveDependencies(unfinishedTypes[key], key);
276+
}
277+
}
278+
263279
static PropertyBuilder AddProperty( TypeBuilder addTo, Type shouldBeAdded, string name )
264280
{
265281
const MethodAttributes propertyMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

src/Common.OData.ApiExplorer/AspNet.OData/PropertyDependency.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,23 @@ internal class PropertyDependency
1010
/// <summary>
1111
/// Initializes a new instance of the <see cref="PropertyDependency"/> class.
1212
/// </summary>
13-
/// <param name="dependentType">The type that contains the dependent property.</param>
1413
/// <param name="dependentOnTypeKey">The key of the type the property has a dependency on.</param>
1514
/// <param name="propertyName">The name of the property.</param>
1615
/// <param name="isCollection">Whether the property is a collection or not.</param>
17-
internal PropertyDependency( TypeBuilder dependentType, EdmTypeKey dependentOnTypeKey, bool isCollection, string propertyName )
16+
internal PropertyDependency( EdmTypeKey dependentOnTypeKey, bool isCollection, string propertyName )
1817
{
19-
Arg.NotNull<TypeBuilder>( dependentType, nameof(dependentType) );
2018
Arg.NotNull<EdmTypeKey>( dependentOnTypeKey, nameof( dependentOnTypeKey ) );
2119
Arg.NotNull<string>( propertyName, nameof( propertyName ) );
2220

23-
DependentType = dependentType;
2421
DependentOnTypeKey = dependentOnTypeKey;
2522
PropertyName = propertyName;
2623
IsCollection = isCollection;
2724
}
2825

2926
/// <summary>
30-
/// Gets the type that has a dependent property.
27+
/// Gets or sets the type that has a dependent property.
3128
/// </summary>
32-
internal TypeBuilder DependentType { get; }
29+
internal TypeBuilder DependentType { get; set; }
3330

3431
/// <summary>
3532
/// Gets the key of the type the property has a dependency on.

0 commit comments

Comments
 (0)