private void AssignLists(IEnumerable <ItemNode> itemNodes) { ItemNode source = itemNodes.First(n => n.HasFlag(NodeFlags.Source)); foreach (ItemNode itemNode in itemNodes.Where(n => !n.HasFlag(NodeFlags.Source))) { ItemNode parentItem = source.Metadata.MemberOf.Equals(itemNode.Metadata.Parent.MemberOf) ? source : itemNodes.FirstOrDefault(n => n.Metadata == itemNode.Metadata.Parent.MemberOf); MemberNode listMember = parentItem.FindNode(itemNode.Metadata.Parent); MemberNode listParent = parentItem.FindNode(listMember.Metadata.Parent) ?? parentItem; ListNode listNode = new ListNode() { Metadata = listMember.Metadata, FieldIndex = listMember.FieldIndex, Flags = NodeFlags.List, Item = itemNode, }; if (listMember.HasFlag(NodeFlags.Source)) { listNode.Flags |= NodeFlags.Source; listNode.FieldIndex = null; } else if (listMember.HasFlag(NodeFlags.Field)) { listNode.Flags |= NodeFlags.Field; } listParent.Members.Remove(listMember); listParent.Members.Add(listNode); itemNode.List = listNode; } }
private Expression GetAssignFieldExpression(Expression parent, MemberNode memberNode, ItemNode itemNode) { Expression value = this.GetValueExpression(parent, memberNode); List <Expression> expressions = new List <Expression>(); if (memberNode.HasFlag(NodeFlags.Field | NodeFlags.Source)) { Expression arrayAccess = Expression.ArrayAccess(this.args.Fields, Expression.Constant(memberNode.FieldIndex.Value)); Expression assign = Expression.Assign(arrayAccess, this.args.Source); expressions.Add(assign); } else if (memberNode.HasFlag(NodeFlags.Field)) { Expression arrayAccess = Expression.ArrayAccess(this.args.Fields, Expression.Constant(memberNode.FieldIndex.Value)); Expression name = this.GetNameExpression(itemNode, memberNode); Expression attribute = this.GetAttributeExpression(memberNode); Expression index = this.GetEnumeratorIndex(itemNode.List); Expression binder = this.GetBinderExpression(memberNode); Expression model = this.args.Model; ConstructorInfo constructor = typeof(Field <,>).MakeGenericType(value.Type, parent.Type).GetConstructors()[0]; Expression newField = Expression.New(constructor, name, attribute, value, parent, binder, index, model); Expression assign = Expression.Assign(arrayAccess, newField); expressions.Add(assign); } if (memberNode.Members.Count > 0) { Expression[] memberExpressions = memberNode.Members.Select(n => this.GetAssignFieldExpression(value, n, itemNode)).ToArray(); Expression[] missingExpressions = this.GetFieldNodes(memberNode).Select(n => this.GetMissingExpression(itemNode, n)).ToArray(); if (this.IsNotNullableValueType(value.Type)) { expressions.Add(this.GetBlockOrExpression(memberExpressions)); } else { Expression isNull = Expression.ReferenceEqual(value, Expression.Constant(null, value.Type)); Expression ifTrue = this.GetBlockOrExpression(missingExpressions); Expression ifFalse = this.GetBlockOrExpression(memberExpressions); Expression ifBlock = Expression.IfThenElse(isNull, ifTrue, ifFalse); expressions.Add(ifBlock); } } if (memberNode.HasFlag(NodeFlags.List)) { ListNode listNode = (ListNode)memberNode; expressions.Add(this.GetAssignEnumeratorExpression(value, listNode)); } return(this.GetBlockOrExpression(expressions)); }
private Expression GetAttributeExpression(MemberNode memberNode) { if (memberNode.HasFlag(NodeFlags.Source)) { return(Expression.Property(this.args.Source, nameof(IField.Identity))); } return(Expression.ArrayAccess(this.args.Attributes, Expression.Constant(memberNode.FieldIndex.Value))); }
private Expression GetFieldExpression(MemberNode memberNode) { if (memberNode.HasFlag(NodeFlags.Source)) { return(this.args.Source); } else if (memberNode.FieldIndex != null) { return(Expression.ArrayAccess(this.args.Fields, Expression.Constant(memberNode.FieldIndex.Value))); } throw new InvalidOperationException(); }
private Expression GetNameExpression(ItemNode itemNode, MemberNode memberNode) { Expression itemName = this.args.ItemVars[itemNode.ItemIndex]; Expression memberName; if (memberNode.HasFlag(NodeFlags.Item)) { memberName = itemName; } else { Expression name = Expression.Constant(memberNode.Metadata.Identity.Notation.Path(itemNode.Metadata.Identity.Name, memberNode.Metadata.Identity.Name)); memberName = this.GetNotationCombine(itemName, name); } return(memberName); }