Пример #1
0
        public void NamePrefixSequence_Test()
        {
            var context = new DynamicDtoTypeBuildingContext();

            context.CurrentPrefix.ShouldBeEmpty();

            const string level1 = "1-level";
            const string level2 = "2-level";
            const string level3 = "3-level";

            using (context.OpenNamePrefix(level1))
            {
                context.CurrentPrefix.ShouldBe(level1);

                using (context.OpenNamePrefix(level2))
                {
                    context.CurrentPrefix.ShouldBe($"{level1}.{level2}");

                    using (context.OpenNamePrefix(level3))
                    {
                        context.CurrentPrefix.ShouldBe($"{level1}.{level2}.{level3}");
                    }

                    context.CurrentPrefix.ShouldBe($"{level1}.{level2}");
                }

                context.CurrentPrefix.ShouldBe(level1);
            }

            context.CurrentPrefix.ShouldBeEmpty();
        }
Пример #2
0
        public async Task BuildDynamicDto_WidthDtoReferences_Test()
        {
            var entityConfigCacheMock = new Mock <IEntityConfigCache>();

            const string area1PropName = nameof(Person.AreaLevel1);

            entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>()))
            .Returns(() => {
                var result = new EntityPropertyDtoList();
                result.Add(new EntityPropertyDto
                {
                    Name       = area1PropName,
                    DataType   = DataTypes.EntityReference,
                    EntityType = "Shesha.Core.Area",
                });

                var r = result as List <EntityPropertyDto>;
                return(Task.FromResult(r));
            });

            var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>();
            var cacheManager      = LocalIocManager.Resolve <ICacheManager>();
            var builder           = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager);

            var baseDtoType = typeof(DynamicDto <Person, Guid>);

            var context = new DynamicDtoTypeBuildingContext()
            {
                ModelType = baseDtoType,
                UseDtoForEntityReferences = true,
                // AddFormFieldsProperty = false // note: false is a default value for AddFormFieldsProperty. Leave it blank to test default value
            };
            var proxyType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context);

            proxyType.Assembly.IsDynamic.ShouldBeTrue();

            var properties = proxyType.GetProperties();

            properties.ShouldContain(p => p.Name == area1PropName);
            proxyType.ShouldNotBeAssignableTo(typeof(IHasFormFieldsList));

            var area1Prop = properties.FirstOrDefault(p => p.Name == area1PropName);

            area1Prop.ShouldNotBeNull($"{area1PropName} property is missing in the created DTO");

            var area1IsDto = area1Prop.PropertyType == typeof(EntityWithDisplayNameDto <Guid>);

            area1IsDto.ShouldBeTrue($"{area1PropName} is not mapped as '{nameof(EntityWithDisplayNameDto<Guid>)}'");
        }
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            var isProxy = typeof(IDynamicDtoProxy).IsAssignableFrom(context.Type);

            if (!context.Type.IsDynamicDto() || isProxy)
            {
                return;
            }

            var dtoBuilder = StaticContext.IocManager.Resolve <IDynamicDtoTypeBuilder>();

            var builderContext = new DynamicDtoTypeBuildingContext
            {
                ModelType = context.Type
            };
            var dtoType = AsyncHelper.RunSync(async() => await dtoBuilder.BuildDtoFullProxyTypeAsync(builderContext.ModelType, builderContext));

            // build list of properties for case-insensitive search
            var propNames = schema.Properties.Select(p => p.Key.ToLower()).ToList();

            context.SchemaGenerator.GenerateSchema(dtoType, context.SchemaRepository);

            var allProperties = dtoType.GetProperties();

            foreach (var property in allProperties)
            {
                if (propNames.Contains(property.Name.ToLower()))
                {
                    continue;
                }

                var propertySchema = context.SchemaGenerator.GenerateSchema(property.PropertyType, context.SchemaRepository, memberInfo: property);

                // note: Nullable is not processed by GenerateSchema
                propertySchema.Nullable = property.PropertyType.IsNullableType();

                schema.Properties.Add(property.Name.ToCamelCase(), propertySchema);
            }

            // add `_formFields` with comment
            var formFieldsProp = typeof(IHasFormFieldsList).GetProperty(nameof(IHasFormFieldsList._formFields));

            if (!propNames.Contains(formFieldsProp.Name.ToLower()))
            {
                var formFieldsSchema = context.SchemaGenerator.GenerateSchema(formFieldsProp.PropertyType, context.SchemaRepository, memberInfo: formFieldsProp);
                schema.Properties.Add(formFieldsProp.Name, formFieldsSchema);
            }
        }
Пример #4
0
        /// <summary>
        /// Map entity to a custom <see cref="DynamicDto{TEntity, TPrimaryKey}"/>
        /// </summary>
        /// <typeparam name="TDynamicDto">Type of dynamic DTO</typeparam>
        /// <typeparam name="TEntity">Type of entity</typeparam>
        /// <typeparam name="TPrimaryKey">Type of entity primary key</typeparam>
        /// <param name="entity">entity to map</param>
        /// <param name="settings">mapping settings</param>
        /// <returns></returns>
        protected async Task <TDynamicDto> MapToCustomDynamicDtoAsync <TDynamicDto, TEntity, TPrimaryKey>(TEntity entity, IDynamicMappingSettings settings = null)
            where TEntity : class, IEntity <TPrimaryKey>
            where TDynamicDto : class, IDynamicDto <TEntity, TPrimaryKey>
        {
            // build dto type
            var context = new DynamicDtoTypeBuildingContext()
            {
                ModelType = typeof(TDynamicDto),
                UseDtoForEntityReferences = settings?.UseDtoForEntityReferences ?? false
            };
            var dtoType = await DtoBuilder.BuildDtoFullProxyTypeAsync(typeof(TDynamicDto), context);

            var dto = Activator.CreateInstance(dtoType) as TDynamicDto;

            // create mapper
            var mapper = await DynamicDtoMappingHelper.GetEntityToDtoMapperAsync(typeof(TEntity), dtoType);

            // map entity to DTO
            mapper.Map(entity, dto);
            // map dynamic fields
            await DynamicPropertyManager.MapEntityToDtoAsync <TDynamicDto, TEntity, TPrimaryKey>(entity, dto);

            return(dto);
        }
Пример #5
0
        public async Task BuildFullDynamicDto_Test()
        {
            var entityConfigCacheMock = new Mock <IEntityConfigCache>();

            entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>()))
            .Returns(() => {
                var result = new EntityPropertyDtoList();
                result.AddString("Name", "Name...");
                result.AddString("Description", "Description...");


                var r = result as List <EntityPropertyDto>;
                return(Task.FromResult(r));
            });

            var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>();
            var cacheManager      = LocalIocManager.Resolve <ICacheManager>();
            var builder           = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager);

            var baseDtoType = typeof(DynamicDto <Person, Guid>);

            var context = new DynamicDtoTypeBuildingContext()
            {
                ModelType             = baseDtoType,
                AddFormFieldsProperty = true,
            };
            var proxyType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context);

            var properties = proxyType.GetProperties();

            properties.ShouldContain(p => p.Name == "Name");
            properties.ShouldContain(p => p.Name == "Description");
            properties.ShouldContain(p => p.Name == nameof(IHasFormFieldsList._formFields));

            proxyType.ShouldNotBeAssignableTo(typeof(IHasFormFieldsList));
        }
Пример #6
0
        public async Task BuildDynamicDto_Test()
        {
            var entityConfigCacheMock = new Mock <IEntityConfigCache>();

            const string supervisorPropName          = "Supervisor";
            const string supervisorFirstNamePropName = "FirstName";
            const string supervisorLastNamePropName  = "LastName";

            entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>()))
            .Returns(() => {
                var result = new EntityPropertyDtoList();
                result.AddString("Name", "Name...");
                result.AddString("Description", "Description...");

                var nested = new EntityPropertyDto {
                    Name       = supervisorPropName,
                    DataType   = DataTypes.Object,
                    Properties = new List <EntityPropertyDto>(),
                };
                nested.Properties.Add(new EntityPropertyDto {
                    Name = supervisorFirstNamePropName, DataType = DataTypes.String
                });
                nested.Properties.Add(new EntityPropertyDto {
                    Name = supervisorLastNamePropName, DataType = DataTypes.String
                });

                result.Add(nested);


                var r = result as List <EntityPropertyDto>;
                return(Task.FromResult(r));
            });

            var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>();
            var cacheManager      = LocalIocManager.Resolve <ICacheManager>();
            var builder           = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager);

            var baseDtoType = typeof(DynamicDto <Person, Guid>);

            var context = new DynamicDtoTypeBuildingContext()
            {
                ModelType = baseDtoType,
                // AddFormFieldsProperty = false // note: false is a default value for AddFormFieldsProperty. Leave it blank to test default value
            };
            var proxyType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context);

            proxyType.Assembly.IsDynamic.ShouldBeTrue();

            var properties = proxyType.GetProperties();

            properties.ShouldContain(p => p.Name == "Name");
            properties.ShouldContain(p => p.Name == "Description");
            properties.ShouldNotContain(p => p.Name == nameof(IHasFormFieldsList._formFields));
            proxyType.ShouldNotBeAssignableTo(typeof(IHasFormFieldsList));

            var supervisorProp = properties.FirstOrDefault(p => p.Name == supervisorPropName);

            supervisorProp.ShouldNotBeNull($"{supervisorPropName} property is missing in the created DTO");

            // nested object should be dynamic
            supervisorProp.PropertyType.Assembly.IsDynamic.ShouldBeTrue();
            typeof(IDynamicNestedObject).IsAssignableFrom(supervisorProp.PropertyType).ShouldBeTrue($"Dynamic nested object must implement {nameof(IDynamicNestedObject)}");

            var nestedProperties = supervisorProp.PropertyType.GetProperties();

            nestedProperties.ShouldContain(p => p.Name == supervisorFirstNamePropName);
            nestedProperties.ShouldContain(p => p.Name == supervisorLastNamePropName);
        }
        public async Task SaveLoad_Test()
        {
            LoginAsHostAdmin();

            // test data
            var props = new Dictionary <EntityPropertyDto, object>
            {
                { new EntityPropertyDto
                  {
                      Name = "UnitTestDynamicString", DataType = DataTypes.String, Source = MetadataSourceType.UserDefined
                  }, "testString" },
                { new EntityPropertyDto
                  {
                      Name = "UnitTestDynamicDate", DataType = DataTypes.Date, Source = MetadataSourceType.UserDefined
                  }, DateTime.Today },
                { new EntityPropertyDto
                  {
                      Name = "UnitTestDynamicDateTime", DataType = DataTypes.DateTime, Source = MetadataSourceType.UserDefined
                  }, DateTime.Now },
                { new EntityPropertyDto
                  {
                      Name = "UnitTestDynamicBoolean", DataType = DataTypes.Boolean, Source = MetadataSourceType.UserDefined
                  }, true },
                { new EntityPropertyDto
                  {
                      Name = "UnitTestDynamicNumber", DataType = DataTypes.Number, Source = MetadataSourceType.UserDefined
                  }, (decimal)123.45 },
                {
                    new EntityPropertyDto
                    {
                        Name       = "UnitTestDynamicObject", DataType = DataTypes.Object, Source = MetadataSourceType.UserDefined,
                        Properties = new List <EntityPropertyDto>()
                        {
                            new EntityPropertyDto {
                                Name = "UnitTestObjectProperty1", DataType = DataTypes.String, Source = MetadataSourceType.UserDefined
                            },
                            new EntityPropertyDto {
                                Name = "UnitTestObjectProperty2", DataType = DataTypes.String, Source = MetadataSourceType.UserDefined
                            }
                        }
                    },
                    new { UnitTestObjectProperty1 = "testObjectProperty1", UnitTestObjectProperty2 = "testObjectProperty2" }
                }
            };

            // configure DTO
            var entityConfigCacheMock = new Mock <IEntityConfigCache>();

            entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>()))
            .Returns(() =>
            {
                var result = new List <EntityPropertyDto>();
                foreach (var prop in props)
                {
                    result.Add(prop.Key);
                }
                return(Task.FromResult(result));
            });

            var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>();
            var cacheManager      = LocalIocManager.Resolve <ICacheManager>();
            var builder           = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager);
            var baseDtoType       = typeof(DynamicDto <Person, Guid>);
            var context           = new DynamicDtoTypeBuildingContext()
            {
                ModelType = baseDtoType
            };
            var dtoType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context);

            var dto = Activator.CreateInstance(dtoType) as DynamicDto <Person, Guid>;

            var properties = dto?.GetType().GetProperties();

            var serializationManager = Resolve <ISerializationManager>();

            // Update DTO properties values with test data
            foreach (var prop in props)
            {
                var p   = properties?.FirstOrDefault(x => prop.Key.Name.ToLower() == x.Name.ToLower());
                var val = prop.Value;
                if (prop.Key.DataType == DataTypes.Object)
                {
                    val = serializationManager.DeserializeProperty(p?.PropertyType, serializationManager.SerializeProperty(prop.Key, val));
                }
                p?.SetValue(dto, val);
            }

            using (var uow = _unitOfWorkManager.Begin())
            {
                var nhuow   = uow as NhUnitOfWork;
                var session = nhuow?.GetSession();

                // Create temporary Entity Properties configs
                var entityConfigRepo = Resolve <IRepository <EntityConfig, Guid> >();
                var entityPropRepo   = Resolve <IRepository <EntityProperty, Guid> >();
                var config           = entityConfigRepo.GetAll().FirstOrDefault(x =>
                                                                                x.TypeShortAlias == typeof(Person).GetEntityConfiguration().TypeShortAlias);
                foreach (var prop in props)
                {
                    var propConf = new EntityProperty()
                    {
                        EntityConfig = config,
                        Name         = prop.Key.Name,
                        DataType     = prop.Key.DataType,
                        Source       = MetadataSourceType.UserDefined
                    };
                    prop.Key.Id = entityPropRepo.Insert(propConf).Id;
                    foreach (var childProp in prop.Key.Properties)
                    {
                        var childPropConf = new EntityProperty()
                        {
                            ParentProperty = propConf,
                            EntityConfig   = config,
                            Name           = prop.Key.Name,
                            DataType       = prop.Key.DataType,
                            Source         = MetadataSourceType.UserDefined
                        };
                        childProp.Id = entityPropRepo.Insert(childPropConf).Id;
                    }
                }

                session?.Flush();

                try
                {
                    var personRepo             = Resolve <IRepository <Person, Guid> >();
                    var dynamicPropertyManager = new DynamicPropertyManager(
                        Resolve <IRepository <EntityProperty, Guid> >(),
                        Resolve <IRepository <EntityPropertyValue, Guid> >(),
                        Resolve <IEntityConfigurationStore>(),
                        Resolve <IDynamicRepository>()
                        )
                    {
                        DtoTypeBuilder = builder, SerializationManager = serializationManager
                    };

                    // Create temporary entity
                    var entity = new Person();
                    var id     = personRepo.Insert(entity).Id;
                    try
                    {
                        // Save dynamic properties to DB
                        await dynamicPropertyManager.MapDtoToEntityAsync <DynamicDto <Person, Guid>, Person, Guid>(dto,
                                                                                                                   entity);

                        session?.Flush();

                        session?.Clear();

                        // Get entity from DB
                        var newEntity = personRepo.Get(id);

                        // Create new DTO and map values from entity to DTO
                        var newDto = Activator.CreateInstance(dtoType) as DynamicDto <Person, Guid>;
                        await dynamicPropertyManager.MapEntityToDtoAsync <DynamicDto <Person, Guid>, Person, Guid>(newEntity,
                                                                                                                   newDto);

                        // Check values. Values from the DB should be the same as from the test list
                        var newProperties = newDto?.GetType().GetProperties();
                        foreach (var prop in props)
                        {
                            var p        = newProperties?.FirstOrDefault(x => prop.Key.Name.ToLower() == x.Name.ToLower());
                            var dtoValue = p?.GetValue(newDto);
                            if (prop.Key.DataType == DataTypes.Object)
                            {
                                var childProperties = dtoValue.GetType().GetProperties();
                                foreach (var childProp in prop.Key.Properties)
                                {
                                    var childP        = childProperties.FirstOrDefault(x => childProp.Name.ToLower() == x.Name.ToLower());
                                    var dtoChildValue = childP.GetValue(dtoValue);
                                    dtoChildValue.ShouldBe(prop.Value.GetType().GetProperty(childProp.Name).GetValue(prop.Value));
                                }
                            }
                            else
                            {
                                dtoValue.ShouldBe(prop.Value);
                            }
                        }
                    }
                    finally
                    {
                        // delete temporary entity
                        session.CreateSQLQuery($"delete from Core_Persons where id = '{id}'").ExecuteUpdate();
                    }
                }
                finally
                {
                    // delete temporary values and properties configs
                    foreach (var prop in props)
                    {
                        session.CreateSQLQuery($"delete from Frwk_EntityPropertyValues where EntityPropertyId = '{prop.Key.Id}'").ExecuteUpdate();
                        if (prop.Key.DataType == DataTypes.Object)
                        {
                            foreach (var childProp in prop.Key.Properties)
                            {
                                session.CreateSQLQuery($"delete from Frwk_EntityProperties where Id = '{childProp.Id}'").ExecuteUpdate();
                            }
                        }
                        session.CreateSQLQuery($"delete from Frwk_EntityProperties where Id = '{prop.Key.Id}'").ExecuteUpdate();
                    }
                }
            }
        }