Skip to content

Commit 26d3e0d

Browse files
LuukN2commonsensesoftware
authored andcommitted
Use ClrTypeAnnotation for getting clr types.
1 parent c8d7ff7 commit 26d3e0d

File tree

20 files changed

+44
-160
lines changed

20 files changed

+44
-160
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
namespace Microsoft.AspNet.OData
22
{
3-
using Microsoft.OData.Edm;
43
using System;
54
using System.Collections.Generic;
65
using System.ComponentModel.DataAnnotations;
76
using System.Diagnostics.Contracts;
87
using System.Linq;
98
using System.Reflection;
109
using System.Reflection.Emit;
10+
using Microsoft.Extensions.DependencyInjection;
11+
using Microsoft.OData.Edm;
1112

1213
struct ClassProperty
1314
{
@@ -24,27 +25,26 @@ internal ClassProperty( PropertyInfo clrProperty, Type propertyType )
2425
Attributes = AttributesFromProperty( clrProperty );
2526
}
2627

27-
internal ClassProperty( IServiceProvider services, IEnumerable<Assembly> assemblies, IEdmOperationParameter parameter, IModelTypeBuilder typeBuilder )
28+
internal ClassProperty( IServiceProvider services, IEdmOperationParameter parameter, IModelTypeBuilder typeBuilder )
2829
{
2930
Contract.Requires( services != null );
30-
Contract.Requires( assemblies != null );
3131
Contract.Requires( parameter != null );
3232
Contract.Requires( typeBuilder != null );
3333

3434
Name = parameter.Name;
35-
var context = new TypeSubstitutionContext( services, assemblies, typeBuilder );
35+
var context = new TypeSubstitutionContext( services, typeBuilder );
3636

3737
if ( parameter.Type.IsCollection() )
3838
{
3939
var collectionType = parameter.Type.AsCollection();
40-
var elementType = collectionType.ElementType().Definition.GetClrType( assemblies );
40+
var elementType = collectionType.ElementType().Definition.GetClrType( services.GetRequiredService<IEdmModel>() );
4141
var substitutedType = elementType.SubstituteIfNecessary( context );
4242

4343
Type = typeof( IEnumerable<> ).MakeGenericType( substitutedType );
4444
}
4545
else
4646
{
47-
var parameterType = parameter.Type.Definition.GetClrType( assemblies );
47+
var parameterType = parameter.Type.Definition.GetClrType( services.GetRequiredService<IEdmModel>() );
4848

4949
Type = parameterType.SubstituteIfNecessary( context );
5050
}

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

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,19 @@
2727
public sealed class DefaultModelTypeBuilder : IModelTypeBuilder
2828
{
2929
static readonly Type IEnumerableOfT = typeof( IEnumerable<> );
30-
readonly ICollection<Assembly> assemblies;
3130
readonly ConcurrentDictionary<ApiVersion, ModuleBuilder> modules = new ConcurrentDictionary<ApiVersion, ModuleBuilder>();
3231
readonly ConcurrentDictionary<EdmTypeKey, TypeInfo> generatedEdmTypes = new ConcurrentDictionary<EdmTypeKey, TypeInfo>();
3332
readonly ConcurrentDictionary<EdmTypeKey, TypeBuilder> unfinishedTypes = new ConcurrentDictionary<EdmTypeKey, TypeBuilder>();
3433
readonly HashSet<EdmTypeKey> visitedEdmTypes = new HashSet<EdmTypeKey>();
3534
readonly Dictionary<EdmTypeKey, List<PropertyDependency>> dependencies = new Dictionary<EdmTypeKey, List<PropertyDependency>>();
3635

37-
/// <summary>
38-
/// Initializes a new instance of the <see cref="DefaultModelTypeBuilder"/> class.
39-
/// </summary>
40-
/// <param name="assemblies">The <see cref="IEnumerable{T}">sequence</see> of application <see cref="Assembly">assemblies</see>.</param>
41-
public DefaultModelTypeBuilder( IEnumerable<Assembly> assemblies )
42-
{
43-
Arg.NotNull( assemblies, nameof( assemblies ) );
44-
this.assemblies = new HashSet<Assembly>( assemblies );
45-
}
46-
4736
/// <inheritdoc />
48-
public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion )
37+
public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion, IEdmModel edmModel )
4938
{
5039
Arg.NotNull( structuredType, nameof( structuredType ) );
5140
Arg.NotNull( clrType, nameof( clrType ) );
5241
Arg.NotNull( apiVersion, nameof( apiVersion ) );
42+
Arg.NotNull( edmModel, nameof( edmModel ) );
5343
Contract.Ensures( Contract.Result<Type>() != null );
5444

5545
var typeKey = new EdmTypeKey( structuredType, apiVersion );
@@ -88,10 +78,9 @@ public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType,
8878

8979
if ( elementType.IsStructured() )
9080
{
91-
assemblies.Add( clrType.Assembly );
9281
visitedEdmTypes.Add( propertyTypeKey );
9382

94-
var itemType = elementType.Definition.GetClrType( assemblies );
83+
var itemType = elementType.Definition.GetClrType( edmModel );
9584
var elementKey = new EdmTypeKey(elementType, apiVersion);
9685

9786
if ( visitedEdmTypes.Contains( elementKey ) )
@@ -103,7 +92,7 @@ public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType,
10392
continue;
10493
}
10594

106-
var newItemType = NewStructuredType( elementType.ToStructuredType(), itemType, apiVersion );
95+
var newItemType = NewStructuredType( elementType.ToStructuredType(), itemType, apiVersion, edmModel );
10796

10897
if ( newItemType is TypeBuilder )
10998
{
@@ -121,7 +110,7 @@ public Type NewStructuredType( IEdmStructuredType structuredType, Type clrType,
121110
{
122111
if ( !visitedEdmTypes.Contains( propertyTypeKey ) )
123112
{
124-
propertyType = NewStructuredType( structuredTypeRef.ToStructuredType(), propertyType, apiVersion );
113+
propertyType = NewStructuredType( structuredTypeRef.ToStructuredType(), propertyType, apiVersion, edmModel );
125114
if ( propertyType is TypeBuilder )
126115
{
127116
hasUnfinishedTypes = true;
@@ -180,7 +169,7 @@ public Type NewActionParameters( IServiceProvider services, IEdmAction action, A
180169
Contract.Ensures( Contract.Result<Type>() != null );
181170

182171
var name = controllerName + "." + action.FullName() + "Parameters";
183-
var properties = action.Parameters.Where( p => p.Name != "bindingParameter" ).Select( p => new ClassProperty( services, assemblies, p, this ) );
172+
var properties = action.Parameters.Where( p => p.Name != "bindingParameter" ).Select( p => new ClassProperty( services, p, this ) );
184173
var signature = new ClassSignature( name, properties, apiVersion );
185174

186175
return CreateTypeInfoFromSignature( signature );

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ public interface IModelTypeBuilder
2121
/// <param name="structuredType">The <see cref="IEdmStructuredType">structured type</see> to evaluate.</param>
2222
/// <param name="clrType">The CLR <see cref="Type">type</see> mapped to the <paramref name="structuredType">structured type</paramref>.</param>
2323
/// <param name="apiVersion">The <see cref="ApiVersion">API version</see> associated with the type mapping.</param>
24+
/// <param name="edmModel">The <see cref="IEdmModel">EdmModel</see> the structured type belongs to.</param>
2425
/// <returns>The original <paramref name="clrType">CLR type</paramref> or a new, dynamically generated substitute <see cref="Type">type</see>
2526
/// that is a subset of the original <paramref name="clrType">CLR type</paramref>, but maps one-to-one with the
2627
/// <paramref name="structuredType">structured type</paramref>.</returns>
2728
/// <remarks>If a substitution is not required, the original <paramref name="clrType">CLR type</paramref> is returned. When a substitution
2829
/// <see cref="Type">type</see> is generated, it is performed only once per <paramref name="apiVersion">API version</paramref>.</remarks>
29-
Type NewStructuredType( IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion );
30+
Type NewStructuredType( IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion, IEdmModel edmModel );
3031

3132
/// <summary>
3233
/// Creates an returns a strongly-typed definition for OData action parameters.

src/Common.OData.ApiExplorer/AspNet.OData/Routing/ODataRouteBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ void ExpandParameterTemplate( StringBuilder template, IEdmTypeReference typeRefe
290290
return;
291291
}
292292

293-
var type = typeDef.GetClrType( Context.Assemblies );
293+
var type = typeDef.GetClrType( Context.EdmModel );
294294

295295
if ( quotedTypes.TryGetValue( type, out var prefix ) )
296296
{

src/Common.OData.ApiExplorer/AspNet.OData/Routing/ODataRouteBuilderContext.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ sealed partial class ODataRouteBuilderContext
3838
internal IList<ParameterDescriptor> ParameterDescriptions => ActionDescriptor.Parameters;
3939
#endif
4040

41-
internal IEnumerable<Assembly> Assemblies { get; }
42-
4341
internal IEdmModel EdmModel { get; }
4442

4543
internal string RouteTemplate { get; }

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,20 @@
1010
sealed class StructuredTypeResolver
1111
{
1212
readonly IEdmModel model;
13-
readonly HashSet<Assembly> assemblies;
1413

15-
internal StructuredTypeResolver( IEdmModel model, IEnumerable<Assembly> assemblies )
14+
internal StructuredTypeResolver( IEdmModel model )
1615
{
1716
Contract.Requires( model != null );
18-
Contract.Requires( assemblies != null );
1917

2018
this.model = model;
21-
this.assemblies = new HashSet<Assembly>( assemblies );
2219
}
2320

2421
internal IEdmStructuredType GetStructuredType( Type type )
2522
{
2623
Contract.Requires( type != null );
2724

2825
var structuredTypes = model.SchemaElements.OfType<IEdmStructuredType>();
29-
var structuredType = structuredTypes.FirstOrDefault( t => type.Equals( t.GetClrType( assemblies ) ) );
30-
31-
if ( structuredType == null && assemblies.Add( type.Assembly ) )
32-
{
33-
structuredType = structuredTypes.FirstOrDefault( t => type.Equals( t.GetClrType( assemblies ) ) );
34-
}
26+
var structuredType = structuredTypes.FirstOrDefault( t => type.Equals( t.GetClrType( model ) ) );
3527

3628
return structuredType;
3729
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static Type SubstituteIfNecessary( this Type type, TypeSubstitutionContex
4444

4545
var openTypes = new Stack<Type>();
4646
var holder = new Lazy<Tuple<ApiVersion, StructuredTypeResolver>>(
47-
() => Tuple.Create( context.ApiVersion, new StructuredTypeResolver( context.Model, context.Assemblies ) ) );
47+
() => Tuple.Create( context.ApiVersion, new StructuredTypeResolver( context.Model ) ) );
4848

4949
if ( IsSubstitutableGeneric( type, openTypes, out var innerType ) )
5050
{
@@ -56,7 +56,7 @@ public static Type SubstituteIfNecessary( this Type type, TypeSubstitutionContex
5656
return type;
5757
}
5858

59-
var newType = context.ModelTypeBuilder.NewStructuredType( structuredType, innerType, apiVersion );
59+
var newType = context.ModelTypeBuilder.NewStructuredType( structuredType, innerType, apiVersion, context.Model );
6060

6161
if ( innerType.Equals( newType ) )
6262
{
@@ -73,7 +73,7 @@ public static Type SubstituteIfNecessary( this Type type, TypeSubstitutionContex
7373

7474
if ( structuredType != null )
7575
{
76-
type = context.ModelTypeBuilder.NewStructuredType( structuredType, type, apiVersion );
76+
type = context.ModelTypeBuilder.NewStructuredType( structuredType, type, apiVersion, context.Model );
7777
}
7878
}
7979

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

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,14 @@ public class TypeSubstitutionContext
2424
/// Initializes a new instance of the <see cref="TypeSubstitutionContext"/> class.
2525
/// </summary>
2626
/// <param name="model">The <see cref="IEdmModel">EDM model</see> to compare against.</param>
27-
/// <param name="assemblies">The <see cref="IEnumerable{T}">sequence</see> of application <see cref="Assembly">assemblies</see>.</param>
2827
/// <param name="modelTypeBuilder">The associated <see cref="IModelTypeBuilder">model type builder</see>.</param>
29-
public TypeSubstitutionContext( IEdmModel model, IEnumerable<Assembly> assemblies, IModelTypeBuilder modelTypeBuilder )
28+
public TypeSubstitutionContext( IEdmModel model, IModelTypeBuilder modelTypeBuilder )
3029
{
3130
Arg.NotNull( model, nameof( model ) );
32-
Arg.NotNull( assemblies, nameof( assemblies ) );
3331
Arg.NotNull( modelTypeBuilder, nameof( modelTypeBuilder ) );
3432

3533
this.model = new Lazy<IEdmModel>( () => model );
3634
apiVersion = new Lazy<ApiVersion>( () => Model.GetAnnotationValue<ApiVersionAnnotation>( Model )?.ApiVersion ?? ApiVersion.Default );
37-
Assemblies = assemblies;
3835
ModelTypeBuilder = modelTypeBuilder;
3936
}
4037

@@ -43,17 +40,14 @@ public TypeSubstitutionContext( IEdmModel model, IEnumerable<Assembly> assemblie
4340
/// </summary>
4441
/// <param name="serviceProvider">The <see cref="IServiceProvider">service provider</see> that the
4542
/// <see cref="IEdmModel">EDM model</see> can be resolved from.</param>
46-
/// <param name="assemblies">The <see cref="IEnumerable{T}">sequence</see> of application <see cref="Assembly">assemblies</see>.</param>
4743
/// <param name="modelTypeBuilder">The associated <see cref="IModelTypeBuilder">model type builder</see>.</param>
48-
public TypeSubstitutionContext( IServiceProvider serviceProvider, IEnumerable<Assembly> assemblies, IModelTypeBuilder modelTypeBuilder )
44+
public TypeSubstitutionContext( IServiceProvider serviceProvider, IModelTypeBuilder modelTypeBuilder )
4945
{
5046
Arg.NotNull( serviceProvider, nameof( serviceProvider ) );
51-
Arg.NotNull( assemblies, nameof( assemblies ) );
5247
Arg.NotNull( modelTypeBuilder, nameof( modelTypeBuilder ) );
5348

5449
model = new Lazy<IEdmModel>( serviceProvider.GetRequiredService<IEdmModel> );
5550
apiVersion = new Lazy<ApiVersion>( () => Model.GetAnnotationValue<ApiVersionAnnotation>( Model )?.ApiVersion ?? ApiVersion.Default );
56-
Assemblies = assemblies;
5751
ModelTypeBuilder = modelTypeBuilder;
5852
}
5953

@@ -69,12 +63,6 @@ public TypeSubstitutionContext( IServiceProvider serviceProvider, IEnumerable<As
6963
/// <value>The associated <see cref="ApiVersion">API version</see>.</value>
7064
public ApiVersion ApiVersion => apiVersion.Value;
7165

72-
/// <summary>
73-
/// Gets the sequence of known application assemblies.
74-
/// </summary>
75-
/// <value>The <see cref="IEnumerable{T}">sequence</see> of application <see cref="Assembly">assemblies</see>.</value>
76-
public IEnumerable<Assembly> Assemblies { get; }
77-
7866
/// <summary>
7967
/// Gets the model type builder used to create substitution types.
8068
/// </summary>

src/Common.OData.ApiExplorer/OData.Edm/EdmExtensions.cs

Lines changed: 6 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,10 @@
1717

1818
static class EdmExtensions
1919
{
20-
#if WEBAPI
21-
internal static Type GetClrType( this IEdmType edmType, IAssembliesResolver assembliesResolver ) =>
22-
edmType.GetClrType( assembliesResolver.GetAssemblies() );
23-
#endif
24-
25-
internal static Type GetClrType( this IEdmType edmType, IEnumerable<Assembly> assemblies )
20+
internal static Type GetClrType( this IEdmType edmType, IEdmModel edmModel )
2621
{
2722
Contract.Requires( edmType != null );
28-
Contract.Requires( assemblies != null );
23+
Contract.Requires(edmModel != null );
2924

3025
if ( !( edmType is IEdmSchemaType schemaType ) )
3126
{
@@ -40,17 +35,11 @@ internal static Type GetClrType( this IEdmType edmType, IEnumerable<Assembly> as
4035
return type;
4136
}
4237

43-
using ( var matchingTypes = GetMatchingTypes( typeName, assemblies ).GetEnumerator() )
38+
var element = (IEdmSchemaType) edmType;
39+
var annotationValue = edmModel.GetAnnotationValue<ClrTypeAnnotation>(element);
40+
if ( annotationValue != null )
4441
{
45-
if ( matchingTypes.MoveNext() )
46-
{
47-
type = matchingTypes.Current;
48-
49-
if ( !matchingTypes.MoveNext() )
50-
{
51-
return type;
52-
}
53-
}
42+
return annotationValue.ClrType;
5443
}
5544

5645
return null;
@@ -88,56 +77,5 @@ static Type DeriveFromWellKnowPrimitive( string edmFullName )
8877

8978
return null;
9079
}
91-
92-
static string EdmFullName( this Type clrType ) => Format( InvariantCulture, "{0}.{1}", clrType.Namespace, clrType.MangleClrTypeName() );
93-
94-
static string MangleClrTypeName( this Type type )
95-
{
96-
Contract.Requires( type != null );
97-
Contract.Ensures( !IsNullOrEmpty( Contract.Result<string>() ) );
98-
99-
if ( !type.IsGenericType )
100-
{
101-
return type.Name;
102-
}
103-
104-
var typeName = type.Name.Replace( '`', '_' );
105-
var typeArgNames = Join( "_", type.GetGenericArguments().Select( t => t.MangleClrTypeName() ) );
106-
107-
return Format( InvariantCulture, "{0}Of{1}", typeName, typeArgNames );
108-
}
109-
110-
static IEnumerable<Type> GetMatchingTypes( string edmFullName, IEnumerable<Assembly> assemblies ) =>
111-
assemblies.LoadedTypes().Where( t => t.IsPublic && t.EdmFullName() == edmFullName );
112-
113-
static IEnumerable<Type> LoadedTypes( this IEnumerable<Assembly> assemblies )
114-
{
115-
var loadedTypes = new List<Type>();
116-
117-
foreach ( var assembly in assemblies.Where( a => a?.IsDynamic == false ) )
118-
{
119-
var exportedTypes = default( IEnumerable<Type> );
120-
121-
try
122-
{
123-
exportedTypes = assembly.ExportedTypes;
124-
}
125-
catch ( ReflectionTypeLoadException ex )
126-
{
127-
exportedTypes = ex.Types;
128-
}
129-
catch
130-
{
131-
continue;
132-
}
133-
134-
if ( exportedTypes != null )
135-
{
136-
loadedTypes.AddRange( exportedTypes );
137-
}
138-
}
139-
140-
return loadedTypes;
141-
}
14280
}
14381
}

src/Microsoft.AspNet.OData.Versioning.ApiExplorer/AspNet.OData/Routing/ODataRouteBuilderContext.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ internal ODataRouteBuilderContext(
3737
ApiVersion = apiVersion;
3838
serviceProvider = configuration.GetODataRootContainer( route );
3939
EdmModel = serviceProvider.GetRequiredService<IEdmModel>();
40-
Assemblies = configuration.Services.GetAssembliesResolver().GetAssemblies();
4140
routeAttribute = actionDescriptor.GetCustomAttributes<ODataRouteAttribute>().FirstOrDefault();
4241
RouteTemplate = routeAttribute?.PathTemplate;
4342
Route = route;

0 commit comments

Comments
 (0)