Ejemplo n.º 1
0
        public void MapAndDefaultIncludesAttribute()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            Assert.ThrowsException <MultipleDefaultsException>(() => config.Map <RootObject, IncludeByDefaultRootObjectProjection>($"[{nameof(IncludeByDefaultRootObjectProjection.Id)},{nameof(IncludeByDefaultRootObjectProjection.StringValue)}]"));
        }
Ejemplo n.º 2
0
        public void DefaultIncludesAttribute()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.Map <RootObject, IncludeByDefaultRootObjectProjection>();

            var root = new RootObject
            {
                Id                     = Guid.NewGuid(),
                StringValue            = "Name",
                NonIncluded            = "A description",
                ExcludedFromProjection = "Some Details",
                Child                  = new ChildObject
                {
                    Id          = Guid.NewGuid(),
                    Name        = "Name",
                    Description = "Description"
                }
            };

            var result = _expander.Expand(root);

            result.ShouldNotBeNull();

            IncludeByDefaultRootObjectProjection projection = result as IncludeByDefaultRootObjectProjection;

            projection.ShouldNotBeNull();
            projection.StringValue.ShouldBe(root.StringValue);
            projection.Id.ShouldBe(root.Id);

            projection.NonIncluded.ShouldBeNull();
            projection.Child.ShouldBeNull();
        }
Ejemplo n.º 3
0
        public void ExpandFromProof()
        {
            var expander = new Expander();
            var config   = new PopcornConfiguration(expander);

            config.ScanAssemblyForMapping(this.GetType().GetTypeInfo().Assembly);

            ExpandFromClass testObject = new ExpandFromClass {
                Field1 = "field1", Field2 = 2
            };
            var result = (ExpandFromClassProjection)expander.Expand(testObject, null);

            Assert.AreEqual(testObject.Field1, result.Field1);
            Assert.AreEqual(testObject.Field2, result.Field2);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Configure the AspNet Core MVC options to include an Api Expander.  Allow the caller to configure it with an action.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="configure"></param>
        public static void UsePopcorn(this HttpConfiguration options, Action <PopcornConfiguration> configure = null)
        {
            // Create an expander object
            var expander      = new Expander();
            var configuration = new PopcornConfiguration(expander);

            // optionally configure this expander
            if (configure != null)
            {
                configure(configuration);
            }

            // Assign a global expander that'll run on all endpoints
            options.Filters.Add(new ExpandActionFilter(expander, configuration.Context, configuration.Inspector, configuration.ApplyToAllEndpoints));
        }
Ejemplo n.º 5
0
        public void SetupExpanderRegistry()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.Map <UserRelationship, UserRelationship>(config: builder =>
            {
                builder.AlternativeMap <UserRelationshipNameProjection>();
                builder.AlternativeMap <UserRelationshipEmailProjection>();
                builder.AlternativeMap <UserRelationshipMixedProjection>();
            });
            config.Map <User, UserFullProjection>(config: builder =>
            {
                builder.AlternativeMap <UserWithNameProjection>();
                builder.AlternativeMap <UserWithEmailProjection>();
            });
            config.Map <UserCollection, UserCollectionProjection>();
        }
Ejemplo n.º 6
0
        public async Task SimpleExpandLazyLoading()
        {
            using (var context = new TestContext(dbname))
            {
                // Get the employee that has cars lazily loaded
                var employee = await context.Employees.FirstOrDefaultAsync();

                employee.ShouldNotBeNull();
                employee.Cars.ShouldNotBeNull();

                // Set up our expander
                var expander = new Expander();
                var config   = new PopcornConfiguration(expander);
                config.EnableBlindExpansion(true);

                // Expand it and make sure we only have our three expected properties.
                var expanded = (Dictionary <string, object>)expander.Expand(employee);
                expanded.ShouldNotBeNull();
                expanded.Count.ShouldBe(3);
            }
        }
Ejemplo n.º 7
0
        public void Setup()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.MapEntityFramework <Project, ProjectProjection, TestModelContext>(TestModelContext.ConfigureOptions(), null, (definition) => { definition.Translate(o => o.Id, () => Guid.NewGuid()); });
            config.MapEntityFramework <PopcornNetStandardTest.Models.Environment, EnvironmentProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <Credential, CredentialProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <CredentialDefinition, CredentialDefinitionProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <CredentialType, CredentialTypeProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <CredentialKeyValue, CredentialKeyValueProjection, TestModelContext>(TestModelContext.ConfigureOptions());

            using (var db = new TestModelContext())
            {
                db.Database.EnsureDeleted();
            }

            using (var db = new TestModelContext())
            {
                db.Database.EnsureCreated();
            }
        }
Ejemplo n.º 8
0
        public void SetupExpanderRegistry()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.Map <RootObject, RootObjectProjection>($"[{nameof(RootObjectProjection.Id)},{nameof(RootObjectProjection.StringValue)},{nameof(RootObjectProjection.NonIncluded)}]",
                                                          (definition) =>
            {
                definition.Translate(o => o.ValueFromTranslator, () => 5.2);
                definition.Translate(o => o.ComplexFromTranslator, () => new ChildObjectProjection {
                    Id = new Guid(), Name = "Complex trans name", Description = "Complex trans description"
                });
            });

            config.Map <ChildObject, ChildObjectProjection>();
            config.Map <DerivedChildObject, DerivedChildObjectProjection>();
            config.Map <Loop, LoopProjection>();
            config.Map <EntityFromFactory, EntityFromFactoryProjection>();
            config.AssignFactory <EntityFromFactoryProjection>(() => new EntityFromFactoryProjection {
                ShouldBeEmpty = "Generated"
            });
        }
Ejemplo n.º 9
0
        public void Setup()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.MapEntityFramework <Project, ProjectProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <PopcornCoreTest.Models.Environment, EnvironmentProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <Credential, CredentialProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <CredentialDefinition, CredentialDefinitionProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <CredentialType, CredentialTypeProjection, TestModelContext>(TestModelContext.ConfigureOptions());
            config.MapEntityFramework <CredentialKeyValue, CredentialKeyValueProjection, TestModelContext>(TestModelContext.ConfigureOptions());

            using (var db = new TestModelContext())
            {
                db.Database.EnsureDeleted();
            }

            using (var db = new TestModelContext())
            {
                db.Database.EnsureCreated();
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Helper function creating a mapping from a source type to a destination type.  Will attempt to auto-load navigation properties as needed.
        /// </summary>
        /// <param name="optionsBuilder"></param>
        /// <param name="defaultIncludes"></param>
        /// <param name="self">todo: describe self parameter on MapEntityFramework</param>
        /// <typeparam name="TSourceType"></typeparam>
        /// <typeparam name="TDestType"></typeparam>
        /// <typeparam name="TContext"></typeparam>
        /// <returns></returns>
        public static PopcornConfiguration MapEntityFramework <TSourceType, TDestType, TContext>(
            this PopcornConfiguration self,
            DbContextOptionsBuilder <TContext> optionsBuilder,
            string defaultIncludes = null)
            where TContext : DbContext
            where TSourceType : class
            where TDestType : class
        {
            return(self.Map <TSourceType, TDestType>(defaultIncludes, (definition) =>
            {
                definition
                // Before dealing with this object, create a context to use
                .BeforeExpansion((destinationObject, sourceObject, context) =>
                {
                    // Do some reference counting here
                    if (!context.ContainsKey(DbKey))
                    {
                        DbContext db = ConstructDbContextWithOptions(optionsBuilder);
                        try
                        {
                            db.Attach(sourceObject);
                            context[DbKey] = db;
                            context[DbCountKey] = 1;
                        }
                        catch { }
                    }
                    else
                    {
                        context[DbCountKey] = (int)context[DbCountKey] + 1;
                    }
                })
                // Afterwards clean up our resources
                .AfterExpansion((destinationObject, sourceObject, context) =>
                {
                    if (context.ContainsKey(DbKey))
                    {
                        // If the reference count goes to 0, destroy the context
                        var decrementedReferenceCount = (int)context[DbCountKey] - 1;
                        if (decrementedReferenceCount == 0)
                        {
                            (context[DbKey] as IDisposable).Dispose();
                            context.Remove(DbKey);
                            context.Remove(DbCountKey);
                        }
                        else
                        {
                            context[DbCountKey] = decrementedReferenceCount;
                        }
                    }
                });

                // Now, find all navigation properties on this type and configure each one to load from the database if
                // actually requested for expansion
                using (DbContext db = ConstructDbContextWithOptions(optionsBuilder))
                {
                    foreach (var prop in typeof(TSourceType).GetNavigationReferenceProperties(db))
                    {
                        definition.PrepareProperty(prop.Name, (destinationObject, destinationProperty, sourceObject, context) =>
                        {
                            if (context.ContainsKey(DbKey))
                            {
                                var expandDb = context[DbKey] as TContext;
                                expandDb.Attach(sourceObject as TSourceType);
                                expandDb.Entry(sourceObject as TSourceType).Reference(prop.Name).Load();
                            }
                        });
                    }

                    foreach (var prop in typeof(TSourceType).GetNavigationCollectionProperties(db))
                    {
                        definition.PrepareProperty(prop.Name, (destinationObject, destinationProperty, sourceObject, context) =>
                        {
                            if (context.ContainsKey(DbKey))
                            {
                                var expandDb = context[DbKey] as TContext;
                                expandDb.Attach(sourceObject as TSourceType);
                                expandDb.Entry(sourceObject as TSourceType).Collection(prop.Name).Load();
                            }
                        });
                    }
                }
            }));
        }