/// <summary> /// Gets the type of the entity schema data for. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <returns></returns> private EntityTypeSchemaData GetEntitySchemaDataForType(Type entityType) { EntityTypeSchemaData toReturn = null; _entityTypeSchemaDataPerType.TryGetValue(entityType, out toReturn); return(toReturn); }
/// <summary> /// Adds the explorer item for the entity with the name specified to the entity's schemadata object. If it's already present, /// it simply returns that explorer item. /// </summary> /// <param name="entityName">Name of the entity.</param> private void AddEntityExplorerItem(string entityName) { EntityTypeSchemaData entitySchemaData = null; if (!_entityTypeSchemaDataPerEntityName.TryGetValue(entityName, out entitySchemaData)) { return; } if (entitySchemaData.RelatedExplorerItem != null) { return; } // not yet created. var entityNameForElement = entityName.Replace("Entity", ""); var suffix = string.Empty; if (!string.IsNullOrEmpty(entitySchemaData.SuperTypeName)) { suffix = string.Format(" (Sub-type of '{0}')", entitySchemaData.SuperTypeName.Replace("Entity", "")); } entitySchemaData.RelatedExplorerItem = new ExplorerItem(entityNameForElement + suffix, ExplorerItemKind.QueryableObject, ExplorerIcon.Table) { DragText = entityNameForElement, IsEnumerable = true, Children = new List <ExplorerItem>() }; var dummyInstance = entitySchemaData.Factory.Create(); DiscoverEntityFields(dummyInstance, entitySchemaData); }
/// <summary> /// Discovers the entity fields for the entity type specified. /// </summary> /// <param name="instance">The instance.</param> /// <param name="resourceType">Type of the resource.</param> /// <param name="entityType">Type of the entity.</param> /// <param name="customState">State of the custom.</param> private void DiscoverEntityFields(IEntityCore instance, EntityTypeSchemaData entitySchemaData) { var instanceFieldsToTravese = instance.Fields .Where(f => !f.IsPrimaryKey || (f.IsPrimaryKey && (f.ActualContainingObjectName == f.ContainingObjectName))) .ToDictionary(f => f.Name); var allProperties = TypeDescriptor.GetProperties(entitySchemaData.EntityType).Cast <PropertyDescriptor>(); var propertiesToTraverse = allProperties.Where(p => instanceFieldsToTravese.ContainsKey(p.Name)); var childrenCollection = entitySchemaData.RelatedExplorerItem.Children; List <ExplorerItem> toAdd = new List <ExplorerItem>(); foreach (PropertyDescriptor property in propertiesToTraverse) { var field = instance.Fields[property.Name]; bool isPK = false; bool isFK = false; int fieldIndex = -1; if (field == null) { // other property if (typeof(IEntityCore).IsAssignableFrom(property.PropertyType) || typeof(IEntityCollectionCore).IsAssignableFrom(property.PropertyType)) { // entity navigator, done later continue; } else { if (!property.IsBrowsable) { continue; } } } else { isPK = field.IsPrimaryKey; isFK = field.IsForeignKey; fieldIndex = field.FieldIndex; } string propertyText = property.Name; if (isFK) { propertyText += " (FK)"; } var icon = isPK ? ExplorerIcon.Key : ExplorerIcon.Column; if (field.ActualContainingObjectName != field.ContainingObjectName) { // inherited field. propertyText += string.Format(" (Inherited from '{0}')", field.ContainingObjectName.Replace("Entity", "")); icon = ExplorerIcon.Inherited; } toAdd.Add(new ExplorerItem(propertyText, ExplorerItemKind.Property, icon) { DragText = property.Name, Tag = fieldIndex }); } childrenCollection.AddRange(toAdd.OrderBy(i => (int)i.Tag).ThenBy(i => i.Text)); }
/// <summary> /// Gets the schema. /// </summary> /// <returns></returns> internal List <ExplorerItem> GetSchema() { VerifyEntityAssemblyVersion(); // We're only interested in the DataSource(2)<TEntity> returning properties. var queryableProperties = _linqMetaDataType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => typeof(IQueryable).IsAssignableFrom(p.PropertyType)); _entityTypeSchemaDataPerEntityName = new Dictionary <string, EntityTypeSchemaData>(); _entityTypeSchemaDataPerType = new Dictionary <Type, EntityTypeSchemaData>(); // first we discover all entity types. foreach (var property in queryableProperties) { if ((!property.PropertyType.IsGenericType) && !typeof(IQueryable).IsAssignableFrom(property.PropertyType)) { continue; } var entityType = property.PropertyType.GetGenericArguments()[0]; ProduceEntityFactoryDelegate(entityType); var factory = GetFactory(entityType); if (factory == null) { continue; } var dummyInstance = factory.Create(); var entitySchemaData = new EntityTypeSchemaData() { EntityType = entityType, Factory = factory, InheritanceInfo = dummyInstance.GetInheritanceInfo(), LinqMetaDataProperty = property }; _entityTypeSchemaDataPerEntityName[dummyInstance.LLBLGenProEntityName] = entitySchemaData; _entityTypeSchemaDataPerType[entityType] = entitySchemaData; } // traverse all entity type schema data objects we've created and recurse over the types to build all property data foreach (var entityName in _entityTypeSchemaDataPerEntityName.Keys) { AddEntityExplorerItem(entityName); } // second iteration, we discover all navigators. Because all entity types are known we can simply use the lookups foreach (var entityStateData in _entityTypeSchemaDataPerEntityName.Values.Distinct()) { DiscoverEntityNavigators(entityStateData); } return(_entityTypeSchemaDataPerType.Values.Select(v => v.RelatedExplorerItem).ToList()); }
/// <summary> /// Discovers the entity navigators. /// </summary> /// <param name="entitySchemaData">The entity schema data.</param> private void DiscoverEntityNavigators(EntityTypeSchemaData entitySchemaData) { var entityType = entitySchemaData.EntityType; if (entitySchemaData.Factory == null) { throw new InvalidOperationException(string.Format("Factory is null in entitySchemaData for entity '{0}'", entitySchemaData.EntityType.FullName)); } var dummyInstance = entitySchemaData.Factory.Create(); var relationsWithMappedFields = dummyInstance.GetAllRelations().Where(r => !string.IsNullOrEmpty(r.MappedFieldName) && !r.IsHierarchyRelation); var relationPerMappedFieldName = relationsWithMappedFields.ToDictionary(r => r.MappedFieldName); var properties = TypeDescriptor.GetProperties(entityType).Cast <PropertyDescriptor>(); var inheritedProperties = new HashSet <PropertyDescriptor>(DetermineInheritedProperties(entitySchemaData.EntityType, properties)); var childrenCollection = entitySchemaData.RelatedExplorerItem.Children; foreach (PropertyDescriptor property in properties) { if (!(typeof(IEntityCore).IsAssignableFrom(property.PropertyType) || typeof(IEntityCollectionCore).IsAssignableFrom(property.PropertyType))) { // not an entity navigator, continue; } string suffix = string.Empty; bool inherited = false; if (inheritedProperties.Contains(property)) { suffix = string.Format(" (Inherited from '{0}')", property.ComponentType.Name.Replace("Entity", "")); inherited = true; } // relationMapped can be null, in the case of a m:n navigator. IEntityRelation relationMapped = null; relationPerMappedFieldName.TryGetValue(property.Name, out relationMapped); if (typeof(IEntityCore).IsAssignableFrom(property.PropertyType)) { var relatedEntitySchemaData = GetEntitySchemaDataForType(property.PropertyType); // single entity navigator, or property added manually. if (relationMapped == null) { // property added manually, ignore. continue; } var icon = relationMapped.TypeOfRelation == RelationType.ManyToOne ? ExplorerIcon.ManyToOne : ExplorerIcon.OneToOne; if (inherited) { icon = ExplorerIcon.Inherited; } childrenCollection.Add(new ExplorerItem(property.Name + suffix, ExplorerItemKind.ReferenceLink, icon) { DragText = property.Name, HyperlinkTarget = relatedEntitySchemaData == null ? null : relatedEntitySchemaData.RelatedExplorerItem }); continue; } if (typeof(IEntityCollectionCore).IsAssignableFrom(property.PropertyType)) { // collection navigator. We have to determine which entity type is returned from the collection. // First, check if there's a TypeContainedAttribute on the property. If so, use the type in the attribute. If not, // try to determine the type using the linq utils method. Type containedType = null; var typeContainedAttribute = property.Attributes[typeof(TypeContainedAttribute)] as TypeContainedAttribute; if ((typeContainedAttribute != null) && typeContainedAttribute.TypeContainedInCollection != null) { containedType = typeContainedAttribute.TypeContainedInCollection; } else { containedType = LinqUtils.DetermineEntityTypeFromEntityCollectionType(property.PropertyType); } var relatedEntitySchemaData = GetEntitySchemaDataForType(containedType); var icon = relationMapped == null ? ExplorerIcon.ManyToMany : ExplorerIcon.OneToMany; if (inherited) { icon = ExplorerIcon.Inherited; } childrenCollection.Add(new ExplorerItem(property.Name + suffix, ExplorerItemKind.CollectionLink, icon) { DragText = property.Name, HyperlinkTarget = relatedEntitySchemaData == null ? null : relatedEntitySchemaData.RelatedExplorerItem }); } } }