private static BinderResult GetEntityGeneric <T>(IDbEntity entity, IEnumerable entities, string path, string collectionPath, string indexers) where T : class, IDbEntity { BinderResult result = null; IEnumerable <T> typedEntities = entities as IEnumerable <T>; string[] collectionEntityIndexers = indexers.Split(','); List <Tuple <string, object> > collectionEntityKeys = new List <Tuple <string, object> >(); Type type = typeof(T); foreach (string indexer in collectionEntityIndexers) { string[] keyAndValue = indexer.Split('='); collectionEntityKeys.Add(new Tuple <string, object>(keyAndValue[0], Convert.ChangeType(keyAndValue[1], type.GetProperty(keyAndValue[0]).GetGetMethod().ReturnType, null))); } IDbEntity collectionEntity = typedEntities.AsQueryable().WherePrimaryKeysEqual(collectionEntityKeys.ToArray()).SingleOrDefault() as IDbEntity; string actualPath = path; if (collectionEntity != null) { actualPath = DbEntityUtilities.GenerateCollectionItemPath(collectionPath, collectionEntity.PrimaryKeys, collectionEntity.Guid); } result = new BinderResult(collectionEntity, path, actualPath); return(result); }
public static void DepthFirst(IDbEntity entity, Type projectionType, string path, IDictionary <Type, ISet <string> > processedEntities, Action <IDbEntity, string> beforeRecursionAction, Action <IDbEntity, string, string, PropertyInfo> beforePropertyRecursionAction, Func <IDbEntity, IEnumerable <IDbEntity>, string, string, PropertyInfo, IEnumerable <IDbEntity> > beforeCollectionRecursionAction, Action <IDbEntity, IEnumerable <IDbEntity>, string, string, PropertyInfo> afterCollectionRecursionAction, Action <IDbEntity, string> afterRecursionAction) { bool processed = !processedEntities.Add(entity.GetType(), entity.Guid); if (processed) { // Prevents self-referencing entities from causing infinite loops return; } beforeRecursionAction(entity, path); IEnumerable <PropertyInfo> virtualProperties = entity.GetType().GetVirtualProperties(true, true); virtualProperties = virtualProperties.Where(ep => projectionType.GetProperties().Any(pp => ep.Name.Equals(pp.Name))); foreach (PropertyInfo property in virtualProperties) { PropertyInfo projectionProperty = projectionType.GetProperty(property.Name); //PropertyInfo projectionProperty = property; string propertyPath = DbEntityUtilities.GeneratePropertyPath(path, property.Name); beforePropertyRecursionAction(entity, path, propertyPath, property); object value = property.GetGetMethod().Invoke(entity, _emptyObjectArray); if (value != null) { if (property.GetGetMethod().ReturnType.IsIEnumerable() && DbEntityUtilities.IsIDbEntity(property.GetGetMethod().ReturnType.GetGenericArguments()[0])) { IEnumerable <IDbEntity> entities = value as IEnumerable <IDbEntity>; entities = beforeCollectionRecursionAction(entity, entities, path, propertyPath, property); for (int i = 0; i < entities.Count(); i++) { DepthFirst(entities.ElementAt(i), projectionProperty.GetGetMethod().ReturnType.GetGenericArguments()[0], DbEntityUtilities.GenerateCollectionItemPath(propertyPath, entities.ElementAt(i).Guid), processedEntities, beforeRecursionAction, beforePropertyRecursionAction, beforeCollectionRecursionAction, afterCollectionRecursionAction, afterRecursionAction); } afterCollectionRecursionAction(entity, entities, path, propertyPath, property); } else if (DbEntityUtilities.IsIDbEntity(property.GetGetMethod().ReturnType)) { DepthFirst(value as IDbEntity, projectionProperty.GetGetMethod().ReturnType, propertyPath, processedEntities, beforeRecursionAction, beforePropertyRecursionAction, beforeCollectionRecursionAction, afterCollectionRecursionAction, afterRecursionAction); } } } afterRecursionAction(entity, path); }