private GenericTypeLookupGraph BuildGenericTypeResolutionGraph(EntityModelSchema model) { var graph = new GenericTypeLookupGraph(); foreach (var unmappedBaseType in model.EntityTypes.Where(e => (e.Annotations.OfType <ObjectLayerOnlyAnnotation>().Any() || e.Annotations.OfType <GenericTypeAnnotation>().Any()) && e.BaseType == null)) { var genericTypeAnnotation = unmappedBaseType.Annotations.OfType <GenericTypeAnnotation>().FirstOrDefault(); if (genericTypeAnnotation == null) { continue; } int count = genericTypeAnnotation.TypeParameters.Count; for (int i = 0; i < count; ++i) { var lookups = new Dictionary <EntityType, GenericArgument>(); var typeParameterName = genericTypeAnnotation.TypeParameters[i]; graph.Add(new GenericTypeParameter(unmappedBaseType, typeParameterName), lookups); this.WalkChildren(graph, model, unmappedBaseType, typeParameterName, lookups); } } return(graph); }
private void WalkChildren(GenericTypeLookupGraph graph, EntityModelSchema model, EntityType baseType, string typeParameterName, Dictionary <EntityType, GenericArgument> lookups) { foreach (var childType in model.EntityTypes.Where(e => e.BaseType == baseType)) { var genericTypeAnnotation = childType.Annotations.OfType <GenericTypeAnnotation>().FirstOrDefault(); var genericArgumentsAnnotation = childType.Annotations.OfType <GenericArgumentsAnnotation>().FirstOrDefault(); GenericArgument argument = null; bool argumentMissing = genericArgumentsAnnotation == null || (argument = genericArgumentsAnnotation.GenericArguments.SingleOrDefault(ga => ga.TypeParameterName == typeParameterName)) == null; if (argumentMissing) { var exception = new TaupoArgumentException( string.Format( CultureInfo.InvariantCulture, "Entity type {0} cannot derive from entity type {1} because {0} does not have a type parameter {2} specified by a {3}.", childType.Name, baseType.Name, typeParameterName, typeof(GenericTypeAnnotation).Name)); if (genericTypeAnnotation == null) { throw exception; } var childTypeParameterPosition = genericTypeAnnotation.TypeParameters.IndexOf(typeParameterName); if (childTypeParameterPosition == -1) { throw exception; } var childLookups = new Dictionary <EntityType, GenericArgument>(); graph.Add(new GenericTypeParameter(childType, typeParameterName), childLookups); this.WalkChildren(graph, model, childType, typeParameterName, childLookups); // Merge the child lookups back into lookups foreach (var kvp in childLookups) { lookups[kvp.Key] = kvp.Value; } } else { lookups[childType] = argument; } } }