public Expression GetInvokingExpression(Expression exp, MapType mapType = MapType.Map) { if (this.IsChildPath) { return(this.Invoker !.Body); } return(this.SourceMemberName != null ? ExpressionEx.PropertyOrFieldPath(exp, this.SourceMemberName) : this.Invoker !.Apply(mapType, exp)); }
protected ClassMapping CreateClassConverter(Expression source, ClassModel classModel, CompileArgument arg, Expression?destination = null) { var destinationMembers = classModel.Members; var unmappedDestinationMembers = new List <string>(); var properties = new List <MemberMapping>(); var sources = new List <Expression> { source }; sources.AddRange( arg.Settings.ExtraSources.Select(src => src is LambdaExpression lambda ? lambda.Apply(arg.MapType, source) : ExpressionEx.PropertyOrFieldPath(source, (string)src))); foreach (var destinationMember in destinationMembers) { if (ProcessIgnores(arg, destinationMember, out var ignore)) { continue; } var resolvers = arg.Settings.ValueAccessingStrategies.AsEnumerable(); if (arg.Settings.IgnoreNonMapped == true) { resolvers = resolvers.Where(ValueAccessingStrategy.CustomResolvers.Contains); } var getter = (from fn in resolvers from src in sources select fn(src, destinationMember, arg)) .FirstOrDefault(result => result != null); var nextIgnore = arg.Settings.Ignore.Next((ParameterExpression)source, (ParameterExpression?)destination, destinationMember.Name); var nextResolvers = arg.Settings.Resolvers.Next(arg.Settings.Ignore, (ParameterExpression)source, destinationMember.Name) .ToList(); var propertyModel = new MemberMapping { DestinationMember = destinationMember, Ignore = ignore, NextResolvers = nextResolvers, NextIgnore = nextIgnore, Source = (ParameterExpression)source, Destination = (ParameterExpression?)destination, UseDestinationValue = arg.MapType != MapType.Projection && destinationMember.UseDestinationValue(arg), }; if (getter != null) { propertyModel.Getter = arg.MapType == MapType.Projection ? getter : getter.ApplyNullPropagation(); properties.Add(propertyModel); } else { if (arg.Settings.IgnoreNonMapped != true && arg.Settings.Unflattening == true && arg.DestinationType.GetDictionaryType() == null && arg.SourceType.GetDictionaryType() == null) { var extra = ValueAccessingStrategy.FindUnflatteningPairs(source, destinationMember, arg) .Next(arg.Settings.Ignore, (ParameterExpression)source, destinationMember.Name); nextResolvers.AddRange(extra); } if (classModel.ConstructorInfo != null) { var info = (ParameterInfo)destinationMember.Info !; if (!info.IsOptional) { if (classModel.BreakOnUnmatched) { return(null !); } unmappedDestinationMembers.Add(destinationMember.Name); } properties.Add(propertyModel); } else if (propertyModel.HasSettings()) { propertyModel.Getter = Expression.New(typeof(Never)); properties.Add(propertyModel); } else if (destinationMember.SetterModifier != AccessModifier.None) { if (classModel.BreakOnUnmatched) { return(null !); } unmappedDestinationMembers.Add(destinationMember.Name); } } } if (arg.Context.Config.RequireDestinationMemberSource && unmappedDestinationMembers.Count > 0 && arg.Settings.SkipDestinationMemberCheck != true) { throw new InvalidOperationException($"The following members of destination class {arg.DestinationType} do not have a corresponding source member mapped or ignored:{string.Join(",", unmappedDestinationMembers)}"); } return(new ClassMapping { ConstructorInfo = classModel.ConstructorInfo, Members = properties, }); }