Expression ArrayContainer(ContainerItemHandler handler) { Debug.Assert(schemaType.IsBondContainer()); var count = Expression.Variable(typeof(int), "count"); var index = Expression.Variable(typeof(int), "index"); var item = Expression.ArrayAccess(value, new Expression[] { index }); var next = Expression.LessThan(Expression.PreIncrementAssign(index), count); return(Expression.Block( new[] { index, count }, Expression.Assign(index, Expression.Constant(-1)), Expression.Assign(count, Expression.ArrayLength(value)), handler(item, next, count))); }
Expression EnumerableContainer(ContainerItemHandler handler) { Debug.Assert(schemaType.IsBondContainer()); var methodGetEnumerator = value.Type.GetMethod(typeof(IEnumerable <>), "GetEnumerator"); Debug.Assert(methodGetEnumerator != null, "Container must provide GetEnumerator method"); var enumerator = Expression.Variable(methodGetEnumerator.ReturnType, "enumerator"); var item = Expression.Property(enumerator, "Current"); var next = Expression.Call(enumerator, moveNext); return(Expression.Block( new[] { enumerator }, Expression.Assign(enumerator, Expression.Call(value, methodGetEnumerator)), handler(item, next, ContainerCount(value)))); }
Expression LinkedListContainer(ContainerItemHandler handler) { Debug.Assert(schemaType.IsBondContainer()); var nodeType = typeof(LinkedListNode <>).MakeGenericType(value.Type.GetGenericArguments()[0]); var node = Expression.Variable(nodeType, "node"); var item = Expression.Property(node, "Value"); var next = Expression.NotEqual( Expression.Condition( Expression.Equal(node, Expression.Constant(null)), Expression.Assign(node, Expression.Property(value, "First")), Expression.Assign(node, Expression.Property(node, "Next"))), Expression.Constant(null)); return(Expression.Block( new[] { node }, Expression.Assign(node, Expression.Constant(null, nodeType)), handler(item, next, ContainerCount(value)))); }
Expression Items(ContainerItemHandler handler) { // If the list is an empty element we won't read anything var isEmpty = Expression.Variable(typeof(bool), "isEmpty"); // Generate the following code for the "next" expression: // if (isEmpty) // { // return false; // } // else // { // while (reader.NodeType == XmlNodeType.Whitespace) reader.Read; // do { reader.Read(); } while (reader.NodeType == XmlNodeType.Whitespace; // // if (reader.NodeType == XmlNodeType.Element) && // reader.LocalName != "Item") // { // throw new InvalidDataException(); // } // // return reader.XmlNode != XmlNodeType.EndElement; // } var whitespace = Expression.Equal(Reader.NodeType, Expression.Constant(XmlNodeType.Whitespace)); var next = Expression.Condition(isEmpty, Expression.Constant(false), Expression.Block( ControlExpression.While(whitespace, Reader.Read()), ControlExpression.DoWhile(Reader.Read(), whitespace), Expression.IfThen( Expression.AndAlso( Expression.Equal(Reader.NodeType, Expression.Constant(XmlNodeType.Element)), Expression.NotEqual(Reader.LocalName, Expression.Constant("Item"))), ParsingError()), Expression.NotEqual(Reader.NodeType, Expression.Constant(XmlNodeType.EndElement)))); return(Expression.Block( new[] { isEmpty }, Expression.Assign(isEmpty, Reader.IsEmptyElement), handler(next))); }
public Expression Container(BondDataType?expectedType, ContainerHandler handler) { if (schemaType.IsBondNullable()) { return(Nullable(handler)); } if (schemaType.IsBondBlob()) { return(BlobContainer(handler)); } var itemType = schemaType.GetValueType(); ContainerItemHandler itemHandler = (item, next, count) => handler( new ObjectParser(this, item, itemType), Expression.Constant(itemType.GetBondDataType()), next, count, null); if (value.Type.IsArray) { return(ArrayContainer(itemHandler)); } if (value.Type.IsGenericType()) { if (typeof(IList <>).MakeGenericType(value.Type.GetTypeInfo().GenericTypeArguments[0]).IsAssignableFrom(value.Type)) { return(ListContainer(itemHandler)); } if (typeof(LinkedList <>) == value.Type.GetGenericTypeDefinition()) { return(LinkedListContainer(itemHandler)); } } return(EnumerableContainer(itemHandler)); }
Expression LinkedListContainer(ContainerItemHandler handler) { Debug.Assert(schemaType.IsBondContainer()); var nodeType = typeof(LinkedListNode<>).MakeGenericType(value.Type.GetGenericArguments()[0]); var node = Expression.Variable(nodeType, "node"); var item = Expression.Property(node, "Value"); var next = Expression.NotEqual( Expression.Condition( Expression.Equal(node, Expression.Constant(null)), Expression.Assign(node, Expression.Property(value, "First")), Expression.Assign(node, Expression.Property(node, "Next"))), Expression.Constant(null)); return Expression.Block( new[] { node }, Expression.Assign(node, Expression.Constant(null, nodeType)), handler(item, next, ContainerCount(value))); }
Expression ArrayContainer(ContainerItemHandler handler) { Debug.Assert(schemaType.IsBondContainer()); var count = Expression.Variable(typeof(int), "count"); var index = Expression.Variable(typeof(int), "index"); var item = Expression.ArrayAccess(value, new Expression[] { index }); var next = Expression.LessThan(Expression.PreIncrementAssign(index), count); return Expression.Block( new[] { index, count }, Expression.Assign(index, Expression.Constant(-1)), Expression.Assign(count, Expression.ArrayLength(value)), handler(item, next, count)); }
Expression EnumerableContainer(ContainerItemHandler handler) { Debug.Assert(schemaType.IsBondContainer()); var methodGetEnumerator = value.Type.GetMethod(typeof(IEnumerable<>), "GetEnumerator"); Debug.Assert(methodGetEnumerator != null, "Container must provide GetEnumerator method"); var enumerator = Expression.Variable(methodGetEnumerator.ReturnType, "enumerator"); var item = Expression.Property(enumerator, "Current"); var next = Expression.Call(enumerator, moveNext); return Expression.Block( new[] { enumerator }, Expression.Assign(enumerator, Expression.Call(value, methodGetEnumerator)), handler(item, next, ContainerCount(value))); }