TypeInfo CreateTypeInfoFromSignature(ClassSignature @class) { Contract.Requires(@class != null); Contract.Ensures(Contract.Result <TypeInfo>() != null); return(CreateTypeBuilderFromSignature(@class).CreateTypeInfo()); }
TypeBuilder CreateTypeBuilderFromSignature(ClassSignature @class) { Contract.Requires(@class != null); Contract.Ensures(Contract.Result <TypeBuilder>() != null); var moduleBuilder = modules.GetOrAdd(@class.ApiVersion, CreateModuleForApiVersion); var typeBuilder = moduleBuilder.DefineType(@class.Name, TypeAttributes.Class); foreach (var attribute in @class.Attributes) { typeBuilder.SetCustomAttribute(attribute); } foreach (var property in @class.Properties) { var type = property.Type; var name = property.Name; var propertyBuilder = AddProperty(typeBuilder, type, name); foreach (var attribute in property.Attributes) { propertyBuilder.SetCustomAttribute(attribute); } } return(typeBuilder); }
static Type ResolveType( EdmTypeKey typeKey, Type clrType, bool clrTypeMatchesEdmType, bool hasUnfinishedTypes, List <ClassProperty> properties, List <PropertyDependency> dependentProperties, BuilderContext context) { var apiVersion = context.ApiVersion; var edmTypes = context.EdmTypes; Type?type; if (clrTypeMatchesEdmType) { if (!edmTypes.TryGetValue(typeKey, out type)) { edmTypes.Add(typeKey, type = clrType.GetTypeInfo()); } return(type); } var signature = new ClassSignature(clrType, properties, apiVersion); if (hasUnfinishedTypes) { if (edmTypes.TryGetValue(typeKey, out type)) { return(type); } var typeBuilder = CreateTypeBuilderFromSignature(context.ModuleBuilder, signature); var dependencies = context.Dependencies; for (var i = 0; i < dependentProperties.Count; i++) { var propertyDependency = dependentProperties[i]; propertyDependency.DependentType = typeBuilder; dependencies.Add(propertyDependency); } edmTypes.Add(typeKey, typeBuilder); return(typeBuilder); } if (!edmTypes.TryGetValue(typeKey, out type)) { edmTypes.Add(typeKey, type = CreateTypeInfoFromSignature(context.ModuleBuilder, signature)); } return(type); }
/// <inheritdoc /> public Type NewActionParameters(IServiceProvider services, IEdmAction action, ApiVersion apiVersion) { Arg.NotNull(services, nameof(services)); Arg.NotNull(action, nameof(action)); Arg.NotNull(apiVersion, nameof(apiVersion)); Contract.Ensures(Contract.Result <Type>() != null); var name = action.FullName() + "Parameters"; var properties = action.Parameters.Where(p => p.Name != "bindingParameter").Select(p => new ClassProperty(services, assemblies, p, this)); var signature = new ClassSignature(name, properties, apiVersion); return(CreateTypeInfoFromSignature(signature)); }
/// <inheritdoc /> public Type NewActionParameters(IServiceProvider services, IEdmAction action, ApiVersion apiVersion, string controllerName) { if (action == null) { throw new ArgumentNullException(nameof(action)); } var name = controllerName + "." + action.FullName() + "Parameters"; var properties = action.Parameters.Where(p => p.Name != "bindingParameter").Select(p => new ClassProperty(services, p, this)); var signature = new ClassSignature(name, properties, apiVersion); var moduleBuilder = modules.GetOrAdd(apiVersion, CreateModuleForApiVersion); return(CreateTypeInfoFromSignature(moduleBuilder, signature)); }
/// <inheritdoc /> public Type NewActionParameters(IServiceProvider services, IEdmAction action, ApiVersion apiVersion, string controllerName) { Arg.NotNull(services, nameof(services)); Arg.NotNull(action, nameof(action)); Arg.NotNull(apiVersion, nameof(apiVersion)); Arg.NotNull(controllerName, nameof(controllerName)); Contract.Ensures(Contract.Result <Type>() != null); var name = controllerName + "." + action.FullName() + "Parameters"; var properties = action.Parameters.Where(p => p.Name != "bindingParameter").Select(p => new ClassProperty(services, p, this)); var signature = new ClassSignature(name, properties, apiVersion); var moduleBuilder = modules.GetOrAdd(apiVersion, CreateModuleForApiVersion); return(CreateTypeInfoFromSignature(moduleBuilder, signature)); }
/// <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 properties = action.Parameters.Where(p => p.Name != "bindingParameter").Select(p => new ClassProperty(services, p, this)); var signature = new ClassSignature(fullTypeName, properties, apiVersion); var moduleBuilder = modules.GetOrAdd(apiVersion, CreateModuleForApiVersion); return(CreateTypeInfoFromSignature(moduleBuilder, signature)); }); return(type); }
/// <inheritdoc /> public Type NewStructuredType(IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion, IEdmModel edmModel) { Arg.NotNull(structuredType, nameof(structuredType)); Arg.NotNull(clrType, nameof(clrType)); Arg.NotNull(apiVersion, nameof(apiVersion)); Arg.NotNull(edmModel, nameof(edmModel)); Contract.Ensures(Contract.Result <Type>() != null); var typeKey = new EdmTypeKey(structuredType, apiVersion); if (generatedEdmTypes.TryGetValue(typeKey, out var generatedType)) { return(generatedType); } visitedEdmTypes.Add(typeKey); const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; var properties = new List <ClassProperty>(); var structuralProperties = structuredType.Properties().ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase); var clrTypeMatchesEdmType = true; var hasUnfinishedTypes = false; var dependentProperties = new List <PropertyDependency>(); foreach (var property in clrType.GetProperties(bindingFlags)) { if (!structuralProperties.TryGetValue(property.Name, out var structuralProperty)) { clrTypeMatchesEdmType = false; continue; } var structuredTypeRef = structuralProperty.Type; var propertyType = property.PropertyType; var propertyTypeKey = new EdmTypeKey(structuredTypeRef, apiVersion); if (structuredTypeRef.IsCollection()) { var collectionType = structuredTypeRef.AsCollection(); var elementType = collectionType.ElementType(); if (elementType.IsStructured()) { visitedEdmTypes.Add(propertyTypeKey); var itemType = elementType.Definition.GetClrType(edmModel); var elementKey = new EdmTypeKey(elementType, apiVersion); if (visitedEdmTypes.Contains(elementKey)) { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; var dependency = new PropertyDependency(elementKey, true, property.Name); dependentProperties.Add(dependency); continue; } var newItemType = NewStructuredType(elementType.ToStructuredType(), itemType, apiVersion, edmModel); if (newItemType is TypeBuilder) { hasUnfinishedTypes = true; } if (!itemType.Equals(newItemType)) { propertyType = IEnumerableOfT.MakeGenericType(newItemType); clrTypeMatchesEdmType = false; } } } else if (structuredTypeRef.IsStructured()) { if (!visitedEdmTypes.Contains(propertyTypeKey)) { propertyType = NewStructuredType(structuredTypeRef.ToStructuredType(), propertyType, apiVersion, edmModel); if (propertyType is TypeBuilder) { hasUnfinishedTypes = true; } } else { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; var dependency = new PropertyDependency(propertyTypeKey, false, property.Name); dependentProperties.Add(dependency); continue; } } clrTypeMatchesEdmType &= property.PropertyType.Equals(propertyType); properties.Add(new ClassProperty(property, propertyType)); } if (clrTypeMatchesEdmType) { return(generatedEdmTypes.GetOrAdd(typeKey, clrType.GetTypeInfo())); } var signature = new ClassSignature(clrType, properties, apiVersion); if (hasUnfinishedTypes) { if (!unfinishedTypes.TryGetValue(typeKey, out var typeBuilder)) { typeBuilder = CreateTypeBuilderFromSignature(signature); foreach (var propertyDependency in dependentProperties) { propertyDependency.DependentType = typeBuilder; } dependencies.Add(typeKey, dependentProperties); ResolveForUnfinishedTypes(); return(ResolveDependencies(typeBuilder, typeKey)); } return(typeBuilder); } return(generatedEdmTypes.GetOrAdd(typeKey, CreateTypeInfoFromSignature(signature))); }
static TypeBuilder CreateTypeBuilderFromSignature(ModuleBuilder moduleBuilder, ClassSignature @class) { var typeBuilder = moduleBuilder.DefineType(@class.Name, TypeAttributes.Class); var attributes = @class.Attributes; var properties = @class.Properties; for (var i = 0; i < attributes.Count; i++) { typeBuilder.SetCustomAttribute(attributes[i]); } for (var i = 0; i < properties.Length; i++) { ref var property = ref properties[i]; var type = property.Type; var name = property.Name; AddProperty(typeBuilder, type, name, property.Attributes); }
static Type CreateTypeInfoFromSignature(ModuleBuilder moduleBuilder, ClassSignature @class) => CreateTypeBuilderFromSignature(moduleBuilder, @class).CreateType() !;
static Type GenerateTypeIfNeeded(IEdmStructuredType structuredType, BuilderContext context) { var apiVersion = context.ApiVersion; var edmTypes = context.EdmTypes; var typeKey = new EdmTypeKey(structuredType, apiVersion); if (edmTypes.TryGetValue(typeKey, out var generatedType)) { return(generatedType); } var edmModel = context.EdmModel; var clrType = structuredType.GetClrType(edmModel); var visitedEdmTypes = context.VisitedEdmTypes; visitedEdmTypes.Add(typeKey); const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; var properties = new List <ClassProperty>(); var structuralProperties = structuredType.Properties().ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase); var clrTypeMatchesEdmType = true; var hasUnfinishedTypes = false; var dependentProperties = new List <PropertyDependency>(); foreach (var property in clrType.GetProperties(bindingFlags)) { if (!structuralProperties.TryGetValue(property.Name, out var structuralProperty)) { clrTypeMatchesEdmType = false; continue; } var structuredTypeRef = structuralProperty.Type; var propertyType = property.PropertyType; var propertyTypeKey = new EdmTypeKey(structuredTypeRef, apiVersion); if (structuredTypeRef.IsCollection()) { var collectionType = structuredTypeRef.AsCollection(); var elementType = collectionType.ElementType(); if (elementType.IsStructured()) { visitedEdmTypes.Add(propertyTypeKey); var itemType = elementType.Definition.GetClrType(edmModel); var elementKey = new EdmTypeKey(elementType, apiVersion); if (visitedEdmTypes.Contains(elementKey)) { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; dependentProperties.Add(new PropertyDependency(elementKey, true, property.Name)); continue; } var newItemType = GenerateTypeIfNeeded(elementType.ToStructuredType(), context); if (newItemType is TypeBuilder) { hasUnfinishedTypes = true; } if (!itemType.Equals(newItemType)) { propertyType = IEnumerableOfT.MakeGenericType(newItemType); clrTypeMatchesEdmType = false; } } } else if (structuredTypeRef.IsStructured()) { if (!visitedEdmTypes.Contains(propertyTypeKey)) { propertyType = GenerateTypeIfNeeded(structuredTypeRef.ToStructuredType(), context); if (propertyType is TypeBuilder) { hasUnfinishedTypes = true; } } else { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; dependentProperties.Add(new PropertyDependency(propertyTypeKey, false, property.Name)); continue; } } clrTypeMatchesEdmType &= property.PropertyType.Equals(propertyType); properties.Add(new ClassProperty(property, propertyType)); } var type = default(TypeInfo); if (clrTypeMatchesEdmType) { if (!edmTypes.TryGetValue(typeKey, out type)) { edmTypes.Add(typeKey, type = clrType.GetTypeInfo()); } return(type); } var signature = new ClassSignature(clrType, properties, apiVersion); if (hasUnfinishedTypes) { if (edmTypes.TryGetValue(typeKey, out type)) { return(type); } var typeBuilder = CreateTypeBuilderFromSignature(context.ModuleBuilder, signature); var dependencies = context.Dependencies; foreach (var propertyDependency in dependentProperties) { propertyDependency.DependentType = typeBuilder; dependencies.Add(propertyDependency); } edmTypes.Add(typeKey, typeBuilder); return(typeBuilder); } if (!edmTypes.TryGetValue(typeKey, out type)) { edmTypes.Add(typeKey, type = CreateTypeInfoFromSignature(context.ModuleBuilder, signature)); } return(type); }
static TypeBuilder CreateTypeBuilderFromSignature(ModuleBuilder moduleBuilder, ClassSignature @class) { Contract.Requires(moduleBuilder != null); Contract.Requires(@class != null); Contract.Ensures(Contract.Result <TypeBuilder>() != null); var typeBuilder = moduleBuilder.DefineType(@class.Name, TypeAttributes.Class); foreach (var attribute in @class.Attributes) { typeBuilder.SetCustomAttribute(attribute); } foreach (var property in @class.Properties) { var type = property.Type; var name = property.Name; AddProperty(typeBuilder, type, name, property.Attributes); } return(typeBuilder); }