private void CreatBindingFromSimple(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
        {
            // 没有特殊的操作
            if (typeSource == typeTarget)
            {
                // 创建成员绑定
                CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
            }
            else
            {
                // 尝试查找mapper
                var externalMapper = GetAndCheckMapper(typeSource, typeTarget, configExpression.Item4);
                // 如果此时未初始化映射器
                externalMapper.CreateMappingExpression(_constructorFunc);
                // 默认情况下,检查对象的null
                Expression mapExpression = externalMapper.GetMemberInitExpression();
                Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(configExpression.Item1.Type), configExpression.Item1.Type);
                // 修改成员
                var expSource = visitorMapper.Visit(configExpression.Item1);
                var changeParamaterVisitor = new ChangParameterExpressionVisitor(expSource);
                mapExpression = changeParamaterVisitor.Visit(mapExpression);
                // 现在可以创建正确的参数。
                Expression checkIfNull = Expression.NotEqual(expSource, defaultExpression);
                // 创建条件
                var checkExpression = Expression.Condition(checkIfNull, mapExpression, Expression.Constant(MapperHelper.GetDefaultValue(mapExpression.Type), mapExpression.Type), mapExpression.Type);
                var bindExpression = Expression.Bind(propTarget, checkExpression);
                // 找到了映射器但没有配置
                if (string.IsNullOrEmpty(configExpression.Item4))
                {
                    configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
                }

                memberForNew.Add(bindExpression);
            }
        }
Exemple #2
0
 private void CreatBindingFromSimple(ref Tuple <Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
 {
     // no specific action.
     if (typeSource == typeTarget)
     {
         // We create the binding.
         CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
     }
     else
     {
         // Try to find a mapper.
         MapperConfigurationBase externalMapper = GetAndCheckMapper(typeSource, typeTarget, configExpression.Item4);
         // If the mapper is not initialized at this moment
         externalMapper.CreateMappingExpression(constructorFunc);
         // By default, check the nullity of the object.
         Expression mapExpression     = externalMapper.GetMemberInitExpression();
         Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(configExpression.Item1.Type), configExpression.Item1.Type);
         // To change the parameter.
         Expression expSource = visitorMapper.Visit(configExpression.Item1, false);
         ChangParameterExpressionVisitor changeParamaterVisitor = new ChangParameterExpressionVisitor(expSource);
         mapExpression = changeParamaterVisitor.Visit(mapExpression);
         // Now we can create with the good parameters.
         Expression checkIfNull = Expression.NotEqual(expSource, defaultExpression);
         // Create condition.
         var checkExpression = Expression.Condition(checkIfNull, mapExpression,
                                                    Expression.Constant(MapperHelper.GetDefaultValue(mapExpression.Type), mapExpression.Type),
                                                    mapExpression.Type);
         MemberAssignment bindExpression = Expression.Bind(propTarget, checkExpression);
         // We find the mapper and not configured.
         if (string.IsNullOrEmpty(configExpression.Item4))
         {
             configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
         }
         memberForNew.Add(bindExpression);
     }
 }
        private void CreateBindingFromList(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
        {
            var sourceTypeList = TypeSystem.GetElementType(typeSource);
            var destTypeList = TypeSystem.GetElementType(typeTarget);
            if (sourceTypeList == destTypeList)
            {
                if (configExpression.Item2.NodeType == ExpressionType.MemberAccess)
                {
                    CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
                }
            }
            // 使用Enumerable类的select方法来更改类型
            else
            {
                var externalMapper = GetAndCheckMapper(sourceTypeList, destTypeList, configExpression.Item4);
                externalMapper.CreateMappingExpression(_constructorFunc);
                MemberAssignment expBind;
                var expSource = configExpression.Item1;
                var visitor = new ChangParameterExpressionVisitor(paramClassSource);
                expSource = visitor.Visit(expSource);

                // 为了与EF / LINQ2SQL兼容。
                var expMappeur = externalMapper.GetGenericLambdaExpression();
                // 创建对Select方法的调用,在Enumerable的Select中插入一个lambda表达式(参数是一个委托),通常情况下,这是不可能的,但(个人认为)编译器就像这样创建并且LINQ2SQL / EF是可以进行sql查询的
                Expression select = Expression.Call(_selectMethod.MakeGenericMethod(sourceTypeList, destTypeList), new[]
                {
                    expSource,
                    expMappeur
                });
                // 创建对ToList方法的调用
                Expression toList = Expression.Call(_toListMethod.MakeGenericMethod(destTypeList), select);

                if (configExpression.Item3) // 如果要检查无效(使用EF / LinqTosql,则不需要)。
                {
                    // 测试source的属性是否为null。
                    Expression checkIfNull = Expression.NotEqual(expSource, Expression.Constant(MapperHelper.GetDefaultValue(expSource.Type), expSource.Type));
                    // 有时候ToList方法不起作用,则使用实现ToList不起作用的类
                    Expression asExp = Expression.TypeAs(toList, propTarget.PropertyType);
                    // 创建条件表达式
                    Expression expCondition = Expression.Condition(checkIfNull, asExp, Expression.Constant(MapperHelper.GetDefaultValue(typeTarget), typeTarget));

                    // 分配给目标属性。
                    expBind = Expression.Bind(propTarget, expCondition);
                }
                else
                {
                    // 分配给目标属性。
                    expBind = Expression.Bind(propTarget, toList);
                }

                // 查找mapper
                if (string.IsNullOrEmpty(configExpression.Item4))
                {
                    configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
                }

                memberForNew.Add(expBind);
            }
        }
        /// <summary>
        /// 为现有目标对象创建成员
        /// </summary>
        public virtual void CreateMemberAssignementForExistingTarget()
        {
            if (PropertiesMapping.Count <= 0)
            {
                return;
            }

            // 用于更改原始表达式的参数。
            var paramTarget = Expression.Parameter(TargetType, paramClassSource.Name.Replace("s", "t"));
            var finalAssign = new List<Expression>();

            foreach (var item in PropertiesMapping)
            {
                var propToAssign = new ChangParameterExpressionVisitor(paramTarget).Visit(item.Item2);
                var assignExpression = new ChangParameterExpressionVisitor(paramClassSource).Visit(item.Item1);
                var sourceType = TypeSystem.GetElementType(item.Item2.Type);
                var targetType = TypeSystem.GetElementType(item.Item1.Type);
                if (string.IsNullOrEmpty(item.Item4))
                {
                    object defaultValue = MapperHelper.GetDefaultValue(item.Item2.Type);
                    Expression defaultExpression = Expression.Constant(defaultValue, item.Item2.Type);
                    Expression checkIfNull = Expression.NotEqual(assignExpression, defaultExpression);
                    if (item.Item3)
                    {
                        Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
                        finalAssign.Add(setIf);
                    }
                    else
                    {
                        if (!IsListOf(propToAssign.Type))
                        {
                            finalAssign.Add(Expression.Assign(propToAssign, assignExpression));
                        }
                        else
                        {
                            if (sourceType == targetType)
                            {
                                Expression toListExp = Expression.Call(_toListMethod.MakeGenericMethod(sourceType), assignExpression);
                                Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
                                finalAssign.Add(setIf);
                                finalAssign.Add(toListExp);
                            }
                        }
                    }
                }
                else // 来自其他映射器。
                {
                    var mapper = GetMapper(sourceType, targetType, false, item.Item4);
                    if (mapper == null)
                    {
                        continue;
                    }

                    mapper.Initialize(_constructorFunc);
                    Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(item.Item2.Type), item.Item2.Type);
                    if (!IsListOf(propToAssign.Type))
                    {
                        ChangParameterExpressionVisitor changeVisitor = new ChangParameterExpressionVisitor(propToAssign, assignExpression);

                        Expression modifiedExpression = changeVisitor.Visit(mapper.expressionForExisting.Body);
                        Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
                        Expression setIf = Expression.IfThen(checkIfNull, modifiedExpression);
                        assignExpression = setIf;
                    }
                    else
                    {
                        Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
                        Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
                        assignExpression = setIf;
                    }

                    finalAssign.Add(assignExpression);
                }
            }

            if (finalAssign.Count > 0 && _delegateCallForExisting == null)
            {
                expressionForExisting = Expression.Lambda(Expression.Block(typeof(void), finalAssign), paramClassSource, paramTarget);
                // 编译
                _delegateCallForExisting = expressionForExisting.Compile();
            }
        }
        /// <summary>
        /// 将表达式分布在此类中更专一的访问方法之一。
        /// </summary>
        /// <param name="node">访问表达式树</param>
        /// <param name="checkIfNullity">检查null值</param>
        /// <returns>
        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
        /// </returns>
        public Expression Visit(Expression node, bool checkIfNullity = false)
        {
            _checkNull = checkIfNullity;
            if (node == null)
            {
                return(node);
            }

            if (_checkNull)
            {
                Expression result;
                switch (node.NodeType)
                {
                case ExpressionType.MemberAccess:
                    result = VisitMember(node as MemberExpression);
                    break;

                case ExpressionType.Parameter:
                    result = VisitParameter(node as ParameterExpression);
                    break;

                case ExpressionType.Convert:
                    result = VisitMember((node as UnaryExpression).Operand as MemberExpression);
                    break;

                case ExpressionType.Lambda:
                    LambdaExpression lambda = ((LambdaExpression)node);
                    // 子表达式树
                    if (lambda.Body.NodeType != ExpressionType.Lambda)
                    {
                        result = Visit(lambda.Body);
                    }
                    else
                    {
                        return(lambda);
                    }

                    break;

                default:
                    result = base.Visit(node);
                    break;
                }

                bool       isFirst            = true;
                Expression previousExpression = null;
                if (_membersToCheck.Count > 1)
                {
                    // 在分配值之前测试所有子对象。例如:source.SubClass.SubClass2.MyProperty。
                    foreach (MemberExpression item in _membersToCheck)
                    {
                        if (!isFirst) // 不要测试该属性的值。
                        {
                            object defaultValue = MapperHelper.GetDefaultValue(item.Type);

                            // 创建默认值的验证。
                            Expression notDefaultValue = Expression.NotEqual(item, Expression.Constant(defaultValue, item.Type));
                            Expression conditional     = null;
                            // 它创建了包含上述条件的条件。
                            if (previousExpression != null)
                            {
                                object defaultPreviousValue = MapperHelper.GetDefaultValue(previousExpression.Type);
                                conditional = Expression.Condition(notDefaultValue, previousExpression, Expression.Constant(defaultPreviousValue, previousExpression.Type));
                            }

                            // 它会影响新创建的条件,这些条件将成为之前的条件。
                            previousExpression = conditional;
                        }
                        else // 属性
                        {
                            previousExpression = item;
                            isFirst            = false;
                        }
                    }

                    return(previousExpression);
                }

                // 不需要递归的元素。
                if (_membersToCheck.Count == 1)
                {
                    var    item         = _membersToCheck.Peek();
                    object defaultValue = MapperHelper.GetDefaultValue(item.Type);
                    // 创建默认值的验证。
                    Expression notDefaultValue = Expression.NotEqual(item, Expression.Constant(defaultValue, item.Type));
                    Expression conditional     = Expression.Condition(notDefaultValue, item, Expression.Constant(defaultValue, item.Type));

                    return(conditional);
                }

                return(result);
            }

            // 默认返回(更改参数),删除lambda表达式的验证。
            if (node.NodeType == ExpressionType.Lambda)
            {
                LambdaExpression lambda = (LambdaExpression)node;
                // 子表达式树
                if (lambda.Body.NodeType != ExpressionType.Call)
                {
                    return(base.Visit(lambda.Body));
                }

                return(lambda);
            }

            return(base.Visit(node));
        }
Exemple #6
0
        private void CreateBindingFromList(ref Tuple <Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
        {
            Type sourceTypeList = TypeSystem.GetElementType(typeSource);
            Type destTypeList   = TypeSystem.GetElementType(typeTarget);

            //No change it's easy
            if (sourceTypeList == destTypeList)
            {
                if (configExpression.Item2.NodeType == ExpressionType.MemberAccess)
                {
                    CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
                }
            }
            // Using "Select" of Enumerable class to change type.
            else
            {
                var externalMapper = GetAndCheckMapper(sourceTypeList, destTypeList, configExpression.Item4);
                externalMapper.CreateMappingExpression(constructorFunc);
                MemberAssignment expBind   = null;
                Expression       expSource = configExpression.Item1;

                ChangParameterExpressionVisitor visitor = new ChangParameterExpressionVisitor(paramClassSource);
                expSource = visitor.Visit(expSource);

                //For compatibility with EF/LINQ2SQL.
                LambdaExpression expMappeur = externalMapper.GetGenericLambdaExpression();
                // We create the call to the Select method.
                // We insert a lambda expression in select of Enumerable(the parameter is a delegate),
                // normally, that's impossible but (we think) that the compiler creating like this and that LINQ2SQL/EF can make the sql query.
                Expression select = Expression.Call(selectMethod.MakeGenericMethod(sourceTypeList, destTypeList),
                                                    new Expression[] { expSource, expMappeur });
                // We create the call to ToList method
                Expression toList = Expression.Call(toListMethod.MakeGenericMethod(destTypeList), select);

                if (configExpression.Item3) // If you want check the nullity(with EF/LinqTosql, you don't need).
                {
                    // Test if the source property is null.
                    Expression checkIfNull  = Expression.NotEqual(expSource, Expression.Constant(MapperHelper.GetDefaultValue(expSource.Type), expSource.Type));
                    Expression expCondition = null;
                    // For boxing some time the ToList method not working.
                    // With a class that implement a list that does not work.
                    Expression asExp = Expression.TypeAs(toList, propTarget.PropertyType);
                    // Create condition
                    expCondition = Expression.Condition(checkIfNull, asExp, Expression.Constant(MapperHelper.GetDefaultValue(typeTarget), typeTarget));

                    // Assigning to the destination propery.
                    expBind = Expression.Bind(propTarget, expCondition);
                }
                else
                {
                    // Assigning to the destination propery.
                    expBind = Expression.Bind(propTarget, toList);
                }
                //We find the mapper
                if (string.IsNullOrEmpty(configExpression.Item4))
                {
                    configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
                }
                memberForNew.Add(expBind);
            }
        }
Exemple #7
0
        internal virtual void CreateMemberAssignementForExistingTarget()
        {
            if (propertiesMapping.Count > 0)
            {
                // For change the parameter of the original expression.
                var paramTarget = Expression.Parameter(TargetType, paramClassSource.Name.Replace("s", "t"));
                ChangParameterExpressionVisitor visitSource = new ChangParameterExpressionVisitor(paramClassSource);
                ChangParameterExpressionVisitor visitTarget = new ChangParameterExpressionVisitor(paramTarget);

                List <Expression> finalAssign = new List <Expression>();

                for (int i = 0; i < propertiesMapping.Count; i++)
                {
                    var        item             = propertiesMapping[i];
                    var        propToAssign     = visitTarget.Visit(item.Item2);
                    Expression assignExpression = null;
                    assignExpression = visitSource.Visit(item.Item1);
                    Type sourceType = TypeSystem.GetElementType(item.Item2.Type);
                    Type targetType = TypeSystem.GetElementType(item.Item1.Type);
                    if (string.IsNullOrEmpty(item.Item4))
                    {
                        object     defaultValue      = MapperHelper.GetDefaultValue(item.Item2.Type);
                        Expression defaultExpression = Expression.Constant(defaultValue, item.Item2.Type);
                        Expression checkIfNull       = Expression.NotEqual(assignExpression, defaultExpression);
                        if (item.Item3)
                        {
                            //Create check if null

                            Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
                            finalAssign.Add(setIf);
                        }
                        else
                        {
                            if (!IsListOf(propToAssign.Type))
                            {
                                finalAssign.Add(Expression.Assign(propToAssign, assignExpression));
                            }
                            else
                            {
                                //NOT TESTED !!!!!
                                if (sourceType == targetType)
                                {
                                    Expression toListExp = Expression.Call(toListMethod.MakeGenericMethod(sourceType), assignExpression);
                                    Expression setIf     = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
                                    finalAssign.Add(setIf);
                                }
                            }
                        }
                    }
                    else   // Come from a other mapper.
                    {
                        var mapper = GetMapper(sourceType, targetType, false, item.Item4);
                        if (mapper != null)
                        {
                            mapper.Initialize(constructorFunc);

                            Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(item.Item2.Type), item.Item2.Type);
                            if (!IsListOf(propToAssign.Type))
                            {
                                ChangParameterExpressionVisitor changeVisitor = new ChangParameterExpressionVisitor(propToAssign, assignExpression);

                                Expression modifiedExpression = changeVisitor.Visit(mapper.expressionForExisting.Body);
                                Expression checkIfNull        = Expression.NotEqual(propToAssign, defaultExpression);
                                Expression setIf = Expression.IfThen(checkIfNull, modifiedExpression);
                                assignExpression = setIf;
                            }
                            else
                            {
                                // Use Select of Enumerable NOT TESTED !!!!!
                                Expression selectExp   = Expression.Call(selectMethod.MakeGenericMethod(sourceType), Expression.Constant(mapper.GetDelegate()));
                                Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
                                Expression setIf       = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
                                assignExpression = setIf;
                            }
                            finalAssign.Add(assignExpression);
                        }
                    }
                }
                if (finalAssign.Count > 0 && delegateCallForExisting == null)
                {
                    expressionForExisting = Expression.Lambda(Expression.Block(typeof(void), finalAssign), paramClassSource, paramTarget);
                    // Assign the delegate.
                    delegateCallForExisting = expressionForExisting.Compile();
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Distributes the expression one of the more specialized visit methods in this class.
        /// </summary>
        /// <param name="node">Expression to visit.</param>
        /// <param name="checkIfNullity">Check</param>
        /// <returns>
        /// Altered expression, if it or any subexpression was modified; otherwise, returns the original expression.
        /// </returns>
        public Expression Visit(Expression node, bool checkIfNullity = false)
        {
            checkNull = checkIfNullity;
            Expression result;

            if (node == null)
            {
                return(node);
            }
            if (checkNull)
            {
                // Treated our case
                switch (node.NodeType)
                {
                case ExpressionType.MemberAccess:
                    result = VisitMember(node as MemberExpression);
                    break;

                case ExpressionType.Parameter:
                    result = VisitParameter(node as ParameterExpression);
                    break;

                case ExpressionType.Convert:
                    result = VisitMember((node as UnaryExpression).Operand as MemberExpression);
                    break;

                case ExpressionType.Lambda:
                    LambdaExpression lambda = ((LambdaExpression)node);
                    //Sub expression
                    if (lambda.Body.NodeType != ExpressionType.Lambda)
                    {
                        result = Visit(lambda.Body);
                    }
                    else
                    {
                        return(lambda);
                    }

                    break;

                default:
                    result = base.Visit(node);
                    break;
                }
                bool       isFirst            = true;
                Expression previousExpression = null;
                if (membersToCheck.Count > 1)
                {
                    // We want to test all the sub objects before assigning the value.
                    // Ex: source.SubClass.SubClass2.MyProperty.
                    // Which will give :
                    // source.SubClass != null ? source.SubClass.SubClass2 != null ? source.SubClass.SubClass2.MyProperty :DefaultValueOfProperty :DefaultValueOfProperty.
                    foreach (MemberExpression item in membersToCheck)
                    {
                        if (!isFirst) // Not to test the value of the property back.
                        {
                            object defaultValue = MapperHelper.GetDefaultValue(item.Type);

                            // Creating verification of default value.
                            Expression notDefaultValue = Expression.NotEqual(item, Expression.Constant(defaultValue, item.Type));
                            Expression conditional     = null;
                            // It creates a condition that includes the above condition.
                            if (previousExpression != null)
                            {
                                object defaultPreviousValue = MapperHelper.GetDefaultValue(previousExpression.Type);
                                conditional = Expression.Condition(notDefaultValue, previousExpression, Expression.Constant(defaultPreviousValue, previousExpression.Type));
                            }
                            // It affects the newly created conditions that will become the previous.
                            previousExpression = conditional;
                        }
                        else // here the requested property.
                        {
                            previousExpression = item;
                            isFirst            = false;
                        }
                    }

                    return(previousExpression);
                }
                // For one element don't need recusrive.
                else if (membersToCheck.Count == 1)
                {
                    var    item         = membersToCheck.Peek();
                    object defaultValue = MapperHelper.GetDefaultValue(item.Type);
                    // Creating verification of default value.
                    Expression notDefaultValue = Expression.NotEqual(item, Expression.Constant(defaultValue, item.Type));
                    Expression conditional;
                    conditional = Expression.Condition(notDefaultValue, item, Expression.Constant(defaultValue, item.Type));

                    return(conditional);
                }
                return(result);
            }
            else
            {
                // Return by default (with change of the parameter).
                // To remove validation of the lambda expression.
                if ((node.NodeType == ExpressionType.Lambda))
                {
                    LambdaExpression lambda = ((LambdaExpression)node);
                    // Sub expression.
                    if (lambda.Body.NodeType != ExpressionType.Call)
                    {
                        return(base.Visit(lambda.Body));
                    }
                    else
                    {
                        return(lambda);
                    }
                }
                else
                {
                    return(base.Visit(node));
                }
            }
        }