Exemple #1
0
        public object CreateEntityAndFillFromDto(TDto dto, string methodCtorName)
        {
            if (!_entityInfo.CanBeCreatedByCtorOrStaticMethod && !_entityInfo.CanBeCreatedViaAutoMapper)
            {
                throw new InvalidOperationException($"I cannot create the entity class {_entityInfo.EntityType.Name} because it has no public constructor, or valid static creator methods.");
            }

            //we look for methods to create/update a new entity in the following order
            //1. A public static method that returns IStatusGeneric (chosing the one with the most parameters that the DTO has too)
            //2. A public parameterised constructor (chosing the one with the most parameters that the DTO has too)
            //3. By creating via parameterless ctor and then using AutoMapper to set the properties

            var decodedName = _dtoInfo.GetSpecifiedName(methodCtorName, CrudTypes.Create);

            if (_entityInfo.CanBeCreatedByCtorOrStaticMethod)
            {
                var ctorStaticToRun = _dtoInfo.GetCtorStaticCreatorToRun(decodedName, _entityInfo);
                var runStatus       = BuildCall.RunMethodOrCtorViaLinq(ctorStaticToRun,
                                                                       dto, ctorStaticToRun.PropertiesMatch.MatchedPropertiesInOrder.ToList(), _context);
                CombineStatuses(runStatus);
                return(runStatus.Result);
            }

            if (_entityInfo.HasPublicParameterlessCtor && _entityInfo.CanBeUpdatedViaProperties)
            {
                var entityInstance = Activator.CreateInstance(_entityInfo.EntityType);
                var mapper         = new CreateMapper(_context, _wrapperMapperConfigs, typeof(TDto), _entityInfo);
                mapper.Accessor.MapDtoToEntity(dto, entityInstance);
                return(entityInstance);
            }

            throw new InvalidOperationException(
                      $"There was no way to create the entity class {_entityInfo.EntityType.Name} using {decodedName.ToString() ?? "any approach"}.");
        }
        public void TestBuildCallMethodNoReturnWithDbContext()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <TestDbContext>();

            using (var context = new TestDbContext(options))
            {
                context.Database.EnsureCreated();

                var prop1  = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, typeof(Dto).GetProperty(nameof(Dto.MyInt)));
                var prop2  = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, null, MatchSources.DbContext, context.GetType());
                var method = typeof(Target1).GetMethod(nameof(Target1.SetMyIntAndAddEntityToDb));
                var dto    = new Dto {
                    MyInt = 123
                };
                var target = new Target1();

                //ATTEMPT
                var action = BuildCall.CallMethodReturnVoid(method, typeof(Dto), typeof(Target1), new List <PropertyMatch> {
                    prop1, prop2
                });
                action.Invoke(dto, target, context);
                context.SaveChanges();

                //VERIFY
                target.MyInt.ShouldEqual(123);
                context.NormalEntities.Count().ShouldEqual(1);
            }
        }
        /// <summary>
        /// This look for methods to update a new entity in the following order
        /// 1. DDD-styled entity: A public access method that fits the DTO
        /// 2. Standard styled entity: using AutoMapper to update the entity</summary>
        /// <param name="dto"></param>
        /// <param name="methodName"></param>
        /// <param name="entity"></param>
        /// <param name="mapper"></param>
        /// <returns></returns>
        private IStatusGeneric RunMethodViaLinq(TDto dto, string methodName, dynamic entity, CreateMapper mapper)
        {
            var decodedName = _dtoInfo.GetSpecifiedName(methodName, CrudTypes.Update);

            if (_entityInfo.CanBeUpdatedViaMethods && decodedName.NameType != DecodedNameTypes.AutoMapper)
            {
                //1. DDD-styled entity: A public access method that fits the DTO

                //This gets one method to run. If it can't be found, or there are too many matches it throws an exception
                var methodToUse = _dtoInfo.GetMethodToRun(decodedName, _entityInfo);

                //This runs the method via LINQ
                return(BuildCall.RunMethodViaLinq(methodToUse.Method,
                                                  dto, entity, methodToUse.PropertiesMatch.MatchedPropertiesInOrder.ToList(), _context));
            }

            if (_entityInfo.CanBeUpdatedViaProperties)
            {
                //2. Standard styled entity: using AutoMapper to update the entity
                mapper.Accessor.MapDtoToEntity(dto, entity);
                return(new StatusGenericHandler());
            }

            throw new InvalidOperationException(
                      $"There was no way to update the entity class {_entityInfo.EntityType.Name} using {decodedName.ToString() ?? "any approach"}.");
        }
Exemple #4
0
        public void TestBuildCallNoParameters()
        {
            //SETUP 
            var method = typeof(Book).GetMethod(nameof(Book.RemovePromotion));
            var target = DddEfTestData.CreateFourBooks().Last();

            //ATTEMPT
            var action = BuildCall.CallMethodReturnVoid(method, typeof(Tests.Dtos.ChangePubDateDto), typeof(Book), new List<PropertyMatch>());
            action.Invoke(target);

            //VERIFY
            target.ActualPrice.ShouldEqual(target.OrgPrice);
        }
Exemple #5
0
        public void TestBuildCallMethodNoReturnAgain()
        {
            //SETUP 
            var prop = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, typeof(Dto).GetProperty(nameof(Dto.MyInt)));
            var method = typeof(Target1).GetMethod(nameof(Target1.SetMyInt));
            var dto = new Dto { MyInt = 123 };
            var target = new Target1();

            //ATTEMPT
            var action = BuildCall.CallMethodReturnVoid(method, typeof(Dto), typeof(Target1), new List<PropertyMatch>{prop});
            action.Invoke(dto, target);

            //VERIFY
            target.MyInt.ShouldEqual(123);
        }
Exemple #6
0
        public void TestBuildCallCtor()
        {
            //SETUP 
            var prop1 = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, typeof(Dto).GetProperty(nameof(Dto.MyInt)));
            var prop2 = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, typeof(Dto).GetProperty(nameof(Dto.MyString)));
            var ctor = typeof(Target1).GetConstructors().Single(x => x.GetParameters().Length == 2);
            var dto = new Dto { MyInt = 123, MyString = "Hello" };

            //ATTEMPT
            var func = BuildCall.CallConstructor(ctor, typeof(Dto), new List<PropertyMatch> { prop1, prop2 });
            var newInstance = func.Invoke(dto);

            //VERIFY
            ((int)newInstance.MyInt).ShouldEqual(123);
            ((string)newInstance.MyString).ShouldEqual("Hello");
        }
Exemple #7
0
        public void TestBuildCallMethodWithReturn()
        {
            //SETUP 
            var prop = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, typeof(Dto).GetProperty(nameof(Dto.MyString)));
            var method = typeof(Target1).GetMethod(nameof(Target1.SetMyString));
            var dto = new Dto { MyString = "Hello" };
            var target = new Target1();

            //ATTEMPT
            var action = BuildCall.CallMethodReturnStatus(method, typeof(Dto), typeof(Target1), new List<PropertyMatch> {prop});
            var status = action.Invoke(dto, target);

            //VERIFY
            target.MyString.ShouldEqual("Hello");
            ((string)status.Message).ShouldEqual("OK");
        }
Exemple #8
0
        public void TestBuildCallChangePubDateDto()
        {
            //SETUP 
            var prop = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, 
                typeof(Tests.Dtos.ChangePubDateDto).GetProperty(nameof(Tests.Dtos.ChangePubDateDto.PublishedOn)));
            var method = typeof(Book).GetMethod(nameof(Book.UpdatePublishedOn));
            var dto = new Tests.Dtos.ChangePubDateDto { PublishedOn = new DateTime(2000,1,1)};
            var target = DddEfTestData.CreateDummyBooks(1).Single();

            //ATTEMPT
            var action = BuildCall.CallMethodReturnVoid(method, typeof(Tests.Dtos.ChangePubDateDto), typeof(Book), new List<PropertyMatch>{prop});
            action.Invoke(dto, target);

            //VERIFY
            target.PublishedOn.ShouldEqual(new DateTime(2000, 1, 1));
        }
Exemple #9
0
        public void TestBuildCallStatic()
        {
            //SETUP 
            var prop1 = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, typeof(Dto).GetProperty(nameof(Dto.MyInt)));
            var prop2 = new PropertyMatch(true, PropertyMatch.TypeMatchLevels.Match, typeof(Dto).GetProperty(nameof(Dto.MyString)));
            var method = typeof(Target1).GetMethod(nameof(Target1.Create));
            var dto = new Dto { MyInt = 123, MyString = "Hello" };

            //ATTEMPT
            var action = BuildCall.CallStaticCreator(method, typeof(Dto), new List<PropertyMatch> { prop1, prop2});
            var status = action.Invoke(dto);

            //VERIFY
            ((string)status.Message).ShouldEqual("Static");
            ((int)status.Result.MyInt).ShouldEqual(123);
            ((string)status.Result.MyString).ShouldEqual("Hello");
        }
Exemple #10
0
        public IStatusGeneric ReadEntityAndUpdateViaDto(TDto dto, string methodName, params Expression <Func <TDto, object> >[] includes)
        {
            //first we need to load it
            var keys   = _context.GetKeysFromDtoInCorrectOrder(dto, _dtoInfo);
            var mapper = new CreateMapper(_context, _configAndMapper, typeof(TDto), _entityInfo);

            var entity = mapper.Accessor.ReturnExistingEntity(keys, includes);

            if (entity == null)
            {
                return(new StatusGenericHandler()
                       .AddError(
                           $"Sorry, I could not find the {_entityInfo.EntityType.GetNameForClass()} you were trying to update."));
            }

            //we look for methods to update a new entity in the following order
            //1. DDD-styled entity: A public access method that fits the DTO
            //2. Standard styled entity: using AutoMapper to update the entity

            var decodedName = _dtoInfo.GetSpecifiedName(methodName, CrudTypes.Update);

            if (_entityInfo.CanBeUpdatedViaMethods && decodedName.NameType != DecodedNameTypes.AutoMapper)
            {
                //1. DDD-styled entity: A public access method that fits the DTO

                //This gets one method to run. If it can't be found, or there are too many matches it throws an exception
                var methodToUse = _dtoInfo.GetMethodToRun(decodedName, _entityInfo);

                //This runs the method via LINQ
                return(BuildCall.RunMethodViaLinq(methodToUse.Method,
                                                  dto, entity, methodToUse.PropertiesMatch.MatchedPropertiesInOrder.ToList(), _context, _createNewDBContext));
            }

            if (_entityInfo.CanBeUpdatedViaProperties)
            {
                //2. Standard styled entity: using AutoMapper to update the entity
                mapper.Accessor.MapDtoToEntity(dto, entity);
                return(new StatusGenericHandler());
            }

            throw new InvalidOperationException(
                      $"There was no way to update the entity class {_entityInfo.EntityType.Name} using {decodedName.ToString() ?? "any approach"}.");
        }