Beispiel #1
0
            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);
            }
Beispiel #2
0
            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);
            }
Beispiel #4
0
            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);
        }