static Type GenerateTypeIfNeeded(IEdmStructuredType structuredType, BuilderContext context) { var typeKey = new EdmTypeKey(structuredType, context.ApiVersion); if (context.EdmTypes.TryGetValue(typeKey, out var generatedType)) { return(generatedType); } var clrType = structuredType.GetClrType(context.EdmModel) !; var visitedEdmTypes = context.VisitedEdmTypes; visitedEdmTypes.Add(typeKey); var properties = new List <ClassProperty>(); var structuralProperties = new Dictionary <string, IEdmProperty>(StringComparer.OrdinalIgnoreCase); var mappedClrProperties = new Dictionary <PropertyInfo, IEdmProperty>(); var dependentProperties = new List <PropertyDependency>(); MapEdmPropertiesToClrProperties(context.EdmModel, structuredType, structuralProperties, mappedClrProperties); var(clrTypeMatchesEdmType, hasUnfinishedTypes) = BuildSignatureProperties( clrType, structuralProperties, mappedClrProperties, properties, dependentProperties, context); return(ResolveType( typeKey, clrType, clrTypeMatchesEdmType, hasUnfinishedTypes, properties, dependentProperties, context)); }
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); }