internal ClassProperty(IServiceProvider services, IEnumerable <Assembly> assemblies, IEdmOperationParameter parameter, IModelTypeBuilder typeBuilder) { Contract.Requires(services != null); Contract.Requires(assemblies != null); Contract.Requires(parameter != null); Contract.Requires(typeBuilder != null); Name = parameter.Name; var context = new TypeSubstitutionContext(services, assemblies, typeBuilder); if (parameter.Type.IsCollection()) { var collectionType = parameter.Type.AsCollection(); var elementType = collectionType.ElementType().Definition.GetClrType(assemblies); var substitutedType = elementType.SubstituteIfNecessary(context); Type = typeof(IEnumerable <>).MakeGenericType(substitutedType); } else { var parameterType = parameter.Type.Definition.GetClrType(assemblies); Type = parameterType.SubstituteIfNecessary(context); } Attributes = AttributesFromOperationParameter(parameter); }
/// <summary> /// Substitutes the specified type, if required. /// </summary> /// <param name="type">The <see cref="Type">type</see> to be evaluated.</param> /// <param name="context">The current <see cref="TypeSubstitutionContext">type substitution context</see>.</param> /// <returns>The original <paramref name="type"/> or a substitution <see cref="Type">type</see> based on the /// provided <paramref name="context"/>.</returns> public static Type SubstituteIfNecessary(this Type type, TypeSubstitutionContext context) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var openTypes = new Stack <Type>(); var apiVersion = context.ApiVersion; var resolver = new StructuredTypeResolver(context.Model); if (IsSubstitutableGeneric(type, openTypes, out var innerType)) { var structuredType = resolver.GetStructuredType(innerType !); if (structuredType == null) { return(type); } var newType = context.ModelTypeBuilder.NewStructuredType(structuredType, innerType !, apiVersion, context.Model); if (innerType !.Equals(newType)) { return(type.ShouldExtractInnerType() ? innerType : type); } return(CloseGeneric(openTypes, newType)); } if (CanBeSubstituted(type)) { var structuredType = resolver.GetStructuredType(type); if (structuredType != null) { type = context.ModelTypeBuilder.NewStructuredType(structuredType, type, apiVersion, context.Model); } } return(type); }
/// <summary> /// Substitutes the specified type, if required. /// </summary> /// <param name="type">The <see cref="Type">type</see> to be evaluated.</param> /// <param name="context">The current <see cref="TypeSubstitutionContext">type substitution context</see>.</param> /// <returns>The original <paramref name="type"/> or a substitution <see cref="Type">type</see> based on the /// provided <paramref name="context"/>.</returns> public static Type SubstituteIfNecessary(this Type type, TypeSubstitutionContext context) { Arg.NotNull(type, nameof(type)); Arg.NotNull(context, nameof(context)); Contract.Ensures(Contract.Result <Type>() != null); var openTypes = new Stack <Type>(); var holder = new Lazy <Tuple <ApiVersion, StructuredTypeResolver> >( () => Tuple.Create(context.ApiVersion, new StructuredTypeResolver(context.Model, context.Assemblies))); if (IsSubstitutableGeneric(type, openTypes, out var innerType)) { var(apiVersion, resolver) = holder.Value; var structuredType = resolver.GetStructuredType(innerType); if (structuredType == null) { return(type); } var newType = context.ModelTypeBuilder.NewStructuredType(structuredType, innerType, apiVersion); if (innerType.Equals(newType)) { return(type.ExtractInnerType() ? innerType : type); } return(CloseGeneric(openTypes, newType)); } if (CanBeSubstituted(type)) { var(apiVersion, resolver) = holder.Value; var structuredType = resolver.GetStructuredType(type); if (structuredType != null) { type = context.ModelTypeBuilder.NewStructuredType(structuredType, type, apiVersion); } } return(type); }
internal ClassProperty(IEdmOperationParameter parameter, TypeSubstitutionContext context) { Name = parameter.Name; if (parameter.Type.IsCollection()) { var collectionType = parameter.Type.AsCollection(); var elementType = collectionType.ElementType().Definition.GetClrType(context.Model) !; var substitutedType = elementType.SubstituteIfNecessary(context); Type = typeof(IEnumerable <>).MakeGenericType(substitutedType); } else { var parameterType = parameter.Type.Definition.GetClrType(context.Model) !; Type = parameterType.SubstituteIfNecessary(context); } Attributes = AttributesFromOperationParameter(parameter).ToArray(); }
/// <inheritdoc /> public Type NewActionParameters(IServiceProvider services, IEdmAction action, ApiVersion apiVersion, string controllerName) { if (action == null) { throw new ArgumentNullException(nameof(action)); } var paramTypes = generatedActionParamsPerVersion.GetOrAdd(apiVersion, _ => new ConcurrentDictionary <EdmTypeKey, Type>()); var fullTypeName = $"{controllerName}.{action.Namespace}.{controllerName}{action.Name}Parameters"; var key = new EdmTypeKey(fullTypeName, apiVersion); var type = paramTypes.GetOrAdd(key, _ => { var context = new TypeSubstitutionContext(services, this, apiVersion); var properties = action.Parameters.Where(p => p.Name != "bindingParameter").Select(p => new ClassProperty(p, context)); var signature = new ClassSignature(fullTypeName, properties, apiVersion); var moduleBuilder = modules.GetOrAdd(apiVersion, CreateModuleForApiVersion); return(CreateTypeInfoFromSignature(moduleBuilder, signature)); }); return(type); }
internal ClassProperty(IServiceProvider services, IEdmOperationParameter parameter, IModelTypeBuilder typeBuilder) { Name = parameter.Name; var context = new TypeSubstitutionContext(services, typeBuilder); var edmModel = services.GetRequiredService <IEdmModel>(); if (parameter.Type.IsCollection()) { var collectionType = parameter.Type.AsCollection(); var elementType = collectionType.ElementType().Definition.GetClrType(edmModel) !; var substitutedType = elementType.SubstituteIfNecessary(context); Type = typeof(IEnumerable <>).MakeGenericType(substitutedType); } else { var parameterType = parameter.Type.Definition.GetClrType(edmModel) !; Type = parameterType.SubstituteIfNecessary(context); } Attributes = AttributesFromOperationParameter(parameter).ToArray(); }