public bool TryMapFromDynamicObject(IMapFromDynamicObjectContext context, out object array) { array = null; if (context.Dto.Type != null) { // Our custom mapping of arrays doesn't contain Type return(false); } if (!context.Dto.TryGet(ArrayType, out object arrayTypeObj)) { return(false); } if (!context.Dto.TryGet(Elements, out object elements)) { return(false); } if (arrayTypeObj is TypeInfo typeInfo) { array = context.MapFromDynamicObjectGraph(elements, typeInfo.ResolveType(context.TypeResolver)); context.AddToCache(array); return(true); } return(false); }
public bool TryMapFromDynamicObject(IMapFromDynamicObjectContext context, out object grouping) { grouping = null; Type type = context.Dto.Type?.ResolveType(context.TypeResolver); if (type == null || !type.IsGenericType || type.GetGenericTypeDefinition() != typeof(IGrouping <,>)) { return(false); } if (!context.Dto.TryGet(Key, out object key)) { return(false); } if (!context.Dto.TryGet(Elements, out object elements)) { return(false); } Type keyType = type.GenericTypeArguments[0]; Type elementType = type.GenericTypeArguments[1]; key = context.MapFromDynamicObjectGraph(key, keyType); elements = context.MapFromDynamicObjectGraph(elements, typeof(List <>).MakeGenericType(elementType)); grouping = MakeGenericGroupingMethod .MakeGenericMethod(keyType, elementType) .Invoke(null, new[] { key, elements }); context.AddToCache(grouping); return(true); }
public bool TryMapFromDynamicObject(IMapFromDynamicObjectContext context, out object collection) { collection = null; Type type = context.Dto.Type?.ResolveType(context.TypeResolver); if (type == null || !type.IsGenericType || type.GetGenericTypeDefinition() != typeof(IEnumerable <>)) { return(false); } if (!context.Dto.TryGet(Elements, out object elements)) { return(false); } Type elementType = type.GenericTypeArguments[0]; // instantiate collection and add it to map Type resultType = context.Dto.TryGet(CollectionType, out object collTypeObj) && collTypeObj is TypeInfo typeInfo ? typeInfo.ResolveType(context.TypeResolver) : typeof(OrderedQueryableList <>).MakeGenericType(elementType); collection = Activator.CreateInstance(resultType); context.AddToCache(collection); // map elements to list AFTER adding to map to avoid endless recursion Type listType = typeof(List <>).MakeGenericType(elementType); elements = context.MapFromDynamicObjectGraph(elements, listType); // copy elements from list to resulting collection try { AddElementsToCollectionMethod.MakeGenericMethod(elementType).Invoke(null, new[] { collection, elements }); } catch (TargetInvocationException e) when(e.InnerException != null) { throw e.InnerException; } return(true); }
public bool TryMapFromDynamicObject(IMapFromDynamicObjectContext context, out object entity) { if (!context.Dto.TryGet(EntityType, out object entityTypeName)) { entity = null; return(false); } if (!(entityTypeName is string)) { entity = null; return(false); } if (context.Dto.TryGet(EntityLoadedNavigations, out object loadedNavigations)) { loadedNavigations = context.MapFromDynamicObjectGraph(loadedNavigations); } entity = context.TryMapEntity(entityTypeName.ToString(), (IReadOnlyList <string>)loadedNavigations); return(entity != null); }
private object TryMapEntity(IMapFromDynamicObjectContext context, string entityTypeName, IReadOnlyList <string> loadedNavigations) { if (!this.entityTypeMap.TryGetValue(entityTypeName, out IEntityType entityType)) { return(null); } // Map only scalar properties for now, navigations have to be set later var valueBuffer = new ValueBuffer( entityType .GetProperties() .Select(p => { object value = context.Dto.Get(p.Name); if (p.GetValueConverter() != null) { value = context.MapFromDynamicObjectGraph(value); value = Utils.ConvertFromProvider(value, p); } return(context.MapFromDynamicObjectGraph(value, p.ClrType)); }) .ToArray()); bool entityIsTracked = loadedNavigations != null; // Get entity instance from EFC's identity map, or create a new one Func <MaterializationContext, object> materializer = this.entityMaterializerSource.GetMaterializer(entityType); var materializationContext = new MaterializationContext(valueBuffer, this.queryContext.Context); object entity = null; IKey pk = entityType.FindPrimaryKey(); if (pk != null) { entity = this.queryContext .QueryBuffer .GetEntity( pk, new EntityLoadInfo( materializationContext, materializer), queryStateManager: entityIsTracked, throwOnNullKey: false); } if (entity == null) { entity = materializer.Invoke(materializationContext); } context.AddToCache(entity); object entityNoRef = entity; if (entityIsTracked) { this.trackEntityActions.Add(sm => { InternalEntityEntry entry = sm.StartTrackingFromQuery(entityType, entityNoRef, valueBuffer, handledForeignKeys: null); foreach (INavigation nav in loadedNavigations.Select(name => entry.EntityType.FindNavigation(name))) { entry.SetIsLoaded(nav); } }); } // Set navigation properties AFTER adding to map to avoid endless recursion foreach (INavigation navigation in entityType.GetNavigations()) { // TODO: shall we skip already loaded navigations if the entity is already tracked? if (context.Dto.TryGet(navigation.Name, out object value) && value != null) { value = context.MapFromDynamicObjectGraph(value, navigation.ClrType); if (navigation.IsCollection()) { // TODO: clear or skip collection if it already contains something? navigation.GetCollectionAccessor().AddRange(entity, ((IEnumerable)value).Cast <object>()); } else { navigation.GetSetter().SetClrValue(entity, value); } } } return(entity); }