示例#1
0
 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));
 }
示例#2
0
        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,
            });
        }