Ejemplo n.º 1
0
        private MemberInitExpression GetAnonymousTypeMemberInitExpression(Dictionary <string, Expression> bindingExpressions, Type oldType)
        {
            Type newAnonymousType = AnonymousTypeFactory.CreateAnonymousType(bindingExpressions.ToDictionary(a => a.Key, a => a.Value.Type));

            TypeMappings.AddTypeMapping(ConfigurationProvider, oldType, newAnonymousType);

            ConfigureAnonymousTypeMaps(oldType, newAnonymousType);
            return(Expression.MemberInit
                   (
                       Expression.New(newAnonymousType),
                       bindingExpressions
                       .ToDictionary(be => be.Key, be => newAnonymousType.GetProperty(be.Key))
                       .Select(member => Expression.Bind(member.Value, bindingExpressions[member.Key]))
                   ));
        }
Ejemplo n.º 2
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            var parameterExpression = node.GetParameterExpression();

            if (parameterExpression == null)
            {
                return(base.VisitMethodCall(node));
            }

            InfoDictionary.Add(parameterExpression, TypeMappings);

            var listOfArgumentsForNewMethod = node.Arguments.Aggregate(new List <Expression>(), (lst, next) =>
            {
                var mappedNext = ArgumentMapper.Create(this, next).MappedArgumentExpression;
                TypeMappings.AddTypeMapping(next.Type, mappedNext.Type);

                lst.Add(mappedNext);
                return(lst);
            });//Arguments could be expressions or other objects. e.g. s => s.UserId  or a string "ZZZ".  For extention methods node.Arguments[0] is usually the helper object itself

            //type args are the generic type args e.g. T1 and T2 MethodName<T1, T2>(method arguments);
            var typeArgsForNewMethod = node.Method.IsGenericMethod
                ? node.Method.GetGenericArguments().Select(i => TypeMappings.ContainsKey(i) ? TypeMappings[i] : i).ToList()//not converting the type it is not in the typeMappings dictionary
                : null;

            MethodCallExpression resultExp;

            if (!node.Method.IsStatic)
            {
                var instance = ArgumentMapper.Create(this, node.Object).MappedArgumentExpression;

                resultExp = node.Method.IsGenericMethod
                    ? Expression.Call(instance, node.Method.Name, typeArgsForNewMethod.ToArray(), listOfArgumentsForNewMethod.ToArray())
                    : Expression.Call(instance, node.Method, listOfArgumentsForNewMethod.ToArray());
            }
            else
            {
                resultExp = node.Method.IsGenericMethod
                    ? Expression.Call(node.Method.DeclaringType, node.Method.Name, typeArgsForNewMethod.ToArray(), listOfArgumentsForNewMethod.ToArray())
                    : Expression.Call(node.Method, listOfArgumentsForNewMethod.ToArray());
            }

            return(resultExp);
        }
Ejemplo n.º 3
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            var parameterExpression = node.GetParameterExpression();

            if (parameterExpression != null)
            {
                InfoDictionary.Add(parameterExpression, TypeMappings);
            }

            var listOfArgumentsForNewMethod = node.Arguments.Aggregate(new List <Expression>(), (lst, next) =>
            {
                var mappedNext = this.Visit(next);
                TypeMappings.AddTypeMapping(ConfigurationProvider, next.Type, mappedNext.Type);

                lst.Add(mappedNext);
                return(lst);
            });//Arguments could be expressions or other objects. e.g. s => s.UserId  or a string "ZZZ".  For extention methods node.Arguments[0] is usually the helper object itself

            //type args are the generic type args e.g. T1 and T2 MethodName<T1, T2>(method arguments);
            var typeArgsForNewMethod = node.Method.IsGenericMethod
                ? node.Method.GetGenericArguments().Select(type => this.TypeMappings.ReplaceType(type)).ToList()//not converting the type it is not in the typeMappings dictionary
                : null;

            ConvertTypesIfNecessary(node.Method.GetParameters(), listOfArgumentsForNewMethod, node.Method);

            return(node.Method.IsStatic
                    ? GetStaticExpression()
                    : GetInstanceExpression(this.Visit(node.Object)));

            MethodCallExpression GetInstanceExpression(Expression instance)
            => node.Method.IsGenericMethod
                    ? Expression.Call(instance, node.Method.Name, typeArgsForNewMethod.ToArray(), listOfArgumentsForNewMethod.ToArray())
                    : Expression.Call(instance, node.Method, listOfArgumentsForNewMethod.ToArray());

            MethodCallExpression GetStaticExpression()
            => node.Method.IsGenericMethod
                    ? Expression.Call(node.Method.DeclaringType, node.Method.Name, typeArgsForNewMethod.ToArray(), listOfArgumentsForNewMethod.ToArray())
                    : Expression.Call(node.Method, listOfArgumentsForNewMethod.ToArray());
        }
Ejemplo n.º 4
0
        protected void FindDestinationFullName(Type typeSource, Type typeDestination, string sourceFullName, List <PropertyMapInfo> propertyMapInfoList)
        {
            const string period = ".";

            bool BothTypesAreAnonymous()
            => IsAnonymousType(typeSource) && IsAnonymousType(typeDestination);

            TypeMap GetTypeMap() => BothTypesAreAnonymous()
                ? anonymousTypesConfigurationProvider.CheckIfTypeMapExists(sourceType: typeDestination, destinationType: typeSource)
                : ConfigurationProvider.CheckIfTypeMapExists(sourceType: typeDestination, destinationType: typeSource);

            //The destination becomes the source because to map a source expression to a destination expression,
            //we need the expressions used to create the source from the destination

            if (typeSource == typeDestination)
            {
                var sourceFullNameArray = sourceFullName.Split(new[] { period[0] }, StringSplitOptions.RemoveEmptyEntries);
                sourceFullNameArray.Aggregate(propertyMapInfoList, (list, next) =>
                {
                    if (list.Count == 0)
                    {
                        AddPropertyMapInfo(typeSource, next, list);
                    }
                    else
                    {
                        var last = list[list.Count - 1];
                        AddPropertyMapInfo(last.CustomExpression == null
                            ? last.DestinationPropertyInfos[last.DestinationPropertyInfos.Count - 1].GetMemberType()
                            : last.CustomExpression.ReturnType, next, list);
                    }
                    return(list);
                });
                return;
            }

            if (GenericTypeDefinitionsAreEquivalent(typeSource, typeDestination))
            {
                if (sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) < 0)
                {
                    //sourceFullName is a member of the generic type definition so just add the members PropertyMapInfo
                    AddPropertyMapInfo(typeDestination, sourceFullName, propertyMapInfoList);
                    var sourceType = typeSource.GetFieldOrProperty(sourceFullName).GetMemberType();
                    var destType   = typeDestination.GetFieldOrProperty(sourceFullName).GetMemberType();

                    TypeMappings.AddTypeMapping(ConfigurationProvider, sourceType, destType);

                    return;
                }
                else
                {
                    //propertyName is a member of the generic type definition so just add the members PropertyMapInfo
                    var propertyName = sourceFullName.Substring(0, sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase));
                    AddPropertyMapInfo(typeDestination, propertyName, propertyMapInfoList);

                    var sourceType = typeSource.GetFieldOrProperty(propertyName).GetMemberType();
                    var destType   = typeDestination.GetFieldOrProperty(propertyName).GetMemberType();

                    TypeMappings.AddTypeMapping(ConfigurationProvider, sourceType, destType);

                    var childFullName = sourceFullName.Substring(sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) + 1);
                    FindDestinationFullName(sourceType, destType, childFullName, propertyMapInfoList);
                    return;
                }
            }

            var typeMap = GetTypeMap();

            PathMap pathMap = typeMap.FindPathMapByDestinationFullPath(destinationFullPath: sourceFullName);

            if (pathMap != null)
            {
                propertyMapInfoList.Add(new PropertyMapInfo(pathMap.CustomMapExpression, new List <MemberInfo>()));
                return;
            }


            if (sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) < 0)
            {
                var propertyMap      = typeMap.GetMemberMapByDestinationProperty(sourceFullName);
                var sourceMemberInfo = typeSource.GetFieldOrProperty(propertyMap.GetDestinationName());
                if (propertyMap.ValueResolverConfig != null)
                {
                    throw new InvalidOperationException(Resource.customResolversNotSupported);
                }

                if (propertyMap.CustomMapExpression == null && !propertyMap.SourceMembers.Any())
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.srcMemberCannotBeNullFormat, typeSource.Name, typeDestination.Name, sourceFullName));
                }

                // CompareSourceAndDestLiterals
                // (
                //     propertyMap.CustomMapExpression != null ? propertyMap.CustomMapExpression.ReturnType : propertyMap.SourceMember.GetMemberType(),
                //     propertyMap.CustomMapExpression != null ? propertyMap.CustomMapExpression.ToString() : propertyMap.SourceMember.Name,
                //     sourceMemberInfo.GetMemberType()
                // );

                // void CompareSourceAndDestLiterals(Type mappedPropertyType, string mappedPropertyDescription, Type sourceMemberType)
                // {
                //     //switch from IsValueType to IsLiteralType because we do not want to throw an exception for all structs
                //     if ((mappedPropertyType.IsLiteralType() || sourceMemberType.IsLiteralType()) && sourceMemberType != mappedPropertyType)
                //         throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.expressionMapValueTypeMustMatchFormat, mappedPropertyType.Name, mappedPropertyDescription, sourceMemberType.Name, propertyMap.GetDestinationName()));
                // }

                if (propertyMap.IncludedMember?.ProjectToCustomSource != null)
                {
                    propertyMapInfoList.Add(new PropertyMapInfo(propertyMap.IncludedMember.ProjectToCustomSource, new List <MemberInfo>()));
                }

                propertyMapInfoList.Add(new PropertyMapInfo(propertyMap.CustomMapExpression, propertyMap.SourceMembers.ToList()));
            }
            else
            {
                var propertyName = sourceFullName.Substring(0, sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase));
                var propertyMap  = typeMap.GetMemberMapByDestinationProperty(propertyName);

                var sourceMemberInfo = typeSource.GetFieldOrProperty(propertyMap.GetDestinationName());
                if (propertyMap.CustomMapExpression == null && !propertyMap.SourceMembers.Any())//If sourceFullName has a period then the SourceMember cannot be null.  The SourceMember is required to find the ProertyMap of its child object.
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.srcMemberCannotBeNullFormat, typeSource.Name, typeDestination.Name, propertyName));
                }

                if (propertyMap.IncludedMember?.ProjectToCustomSource != null)
                {
                    propertyMapInfoList.Add(new PropertyMapInfo(propertyMap.IncludedMember.ProjectToCustomSource, new List <MemberInfo>()));
                }

                propertyMapInfoList.Add(new PropertyMapInfo(propertyMap.CustomMapExpression, propertyMap.SourceMembers.ToList()));
                var childFullName = sourceFullName.Substring(sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) + 1);

                FindDestinationFullName(sourceMemberInfo.GetMemberType(), propertyMap.CustomMapExpression == null
                    ? propertyMap.SourceMember.GetMemberType()
                    : propertyMap.CustomMapExpression.ReturnType, childFullName, propertyMapInfoList);
            }
        }