コード例 #1
0
        // => new App() {Id = p.Id}}
        protected override Expression VisitMemberInit(MemberInitExpression node)
        {
            // 如果有一对多的导航属性会产生嵌套的SQL,这时需要强制主表选择的列里面必须包含导航外键
            // TODO #对 Bindings 进行排序,保证导航属性的赋值一定要最后面#
            // 未实现,在书写表达式时人工保证 ##

            if (node.NewExpression != null)
            {
                this.VisitNewImpl(node.NewExpression);
            }
            if (_navChainHopper.Count == 0)
            {
                _navChainHopper.Add(node.Type.Name);
            }

            for (int i = 0; i < node.Bindings.Count; i++)
            {
                MemberAssignment binding = node.Bindings[i] as MemberAssignment;
                if (binding == null)
                {
                    throw new XFrameworkException("Only 'MemberAssignment' binding supported.");
                }

                Type propertyType = (node.Bindings[i].Member as System.Reflection.PropertyInfo).PropertyType;
                bool isNavigation = !TypeUtils.IsPrimitiveType(propertyType);

                #region 一般属性

                // 非导航属性
                if (!isNavigation)
                {
                    if (binding.Expression.CanEvaluate())
                    {
                        _builder.Append(binding.Expression.Evaluate().Value, binding.Member, node.Type);
                    }
                    else
                    {
                        this.VisitWithoutRemark(x => this.VisitMemberBinding(binding));
                    }

                    // 选择字段
                    this.AddPickColumn(binding.Member.Name);
                }

                #endregion 一般属性

                #region 导航属性

                else
                {
                    // 非显式指定的导航属性需要有 ForeignKeyAttribute
                    if (binding.Expression.NodeType == ExpressionType.MemberAccess && binding.Expression.Acceptable())
                    {
                        var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(binding.Member.DeclaringType);
                        var attribute   = typeRuntime.GetInvokerAttribute <ForeignKeyAttribute>(binding.Member.Name);
                        if (attribute == null)
                        {
                            throw new XFrameworkException("Complex property {{{0}}} must mark 'ForeignKeyAttribute' ", binding.Member.Name);
                        }
                    }

                    // 生成导航属性描述集合,以类名.属性名做为键值
                    int    n       = _navChainHopper.Count;
                    string keyName = _navChainHopper.Count > 0 ? _navChainHopper[_navChainHopper.Count - 1] : string.Empty;
                    keyName = !string.IsNullOrEmpty(keyName) ? keyName + "." + binding.Member.Name : binding.Member.Name;
                    var nav = new Navigation(keyName, binding.Member);
                    if (!_navigations.Contains(keyName))
                    {
                        // fix issue# spliton 列占一个位
                        nav.StartIndex = _pickColumns.Count;
                        nav.FieldCount = GetFieldCount(binding.Expression) + (binding.Expression.NodeType == ExpressionType.MemberAccess && binding.Expression.Acceptable() ? 1 : 0);
                        _navigations.Add(keyName, nav);
                        _navChainHopper.Add(keyName);
                    }

                    // 1.不显式指定导航属性,例:a.Client.ClientList
                    // 2.表达式里显式指定导航属性,例:b
                    if (binding.Expression.NodeType == ExpressionType.MemberAccess)
                    {
                        this.VisitNavigation(binding.Expression as MemberExpression, binding.Expression.Acceptable());
                    }
                    else if (binding.Expression.NodeType == ExpressionType.New)
                    {
                        this.VisitNewImpl(binding.Expression as NewExpression);
                    }
                    else if (binding.Expression.NodeType == ExpressionType.MemberInit)
                    {
                        this.VisitMemberInit(binding.Expression as MemberInitExpression);
                    }

                    // 恢复访问链
                    // 在访问导航属性时可能是 Client.CloudServer,这时要恢复为 Client,以保证能访问 Client 的下一个导航属性
                    if (_navChainHopper.Count != n)
                    {
                        _navChainHopper.RemoveAt(_navChainHopper.Count - 1);
                    }
                }

                #endregion 导航属性
            }

            return(node);
        }