/// <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); }
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(); } } } }