MakeArrayType() public method

public MakeArrayType ( ) : Type
return Type
Example #1
1
        /// <summary>
        ///   Emits an array.
        /// </summary>
        /// <param name="generator"> The generator. </param>
        /// <param name="arrayType"> Type of the array. </param>
        /// <param name="emitElements"> The emit elements. </param>
        public static void EmitArray(this ILGenerator generator, Type arrayType, IList<Action<ILGenerator>> emitElements)
        {
            var tLocal = generator.DeclareLocal(arrayType.MakeArrayType());
            generator.Emit(OpCodes.Ldc_I4, emitElements.Count);
            generator.Emit(OpCodes.Newarr, arrayType);
            generator.EmitStoreLocation(tLocal.LocalIndex);

            for (var i = 0; i < emitElements.Count; i++) {
                generator.EmitLoadLocation(tLocal.LocalIndex);
                generator.Emit(OpCodes.Ldc_I4, i);
                emitElements[i](generator);
                generator.Emit(OpCodes.Stelem_Ref);
            }
            generator.EmitLoadLocation(tLocal.LocalIndex);
        }
		internal Type MakeElementTypes(Type type)
		{
			for (int i = this.m_elementTypes.Length - 1; i >= 0; i--)
			{
				if (this.m_elementTypes[i] == 3)
				{
					type = type.MakeArrayType();
				}
				else
				{
					if (this.m_elementTypes[i] == 2)
					{
						type = type.MakeArrayType(this.m_elementTypes[--i]);
					}
					else
					{
						if (this.m_elementTypes[i] == 1)
						{
							type = type.MakePointerType();
						}
						else
						{
							if (this.m_elementTypes[i] == 4)
							{
								type = type.MakeByRefType();
							}
						}
					}
				}
			}
			return type;
		}
Example #3
0
		public Type Resolve (Type type)
		{
			if (bound)
				return type.MakeArrayType (1);
			else if (dimensions == 1)
				return type.MakeArrayType ();
			return type.MakeArrayType (dimensions);
		}
Example #4
0
 internal Type Resolve(Type type)
 {
     if (_isBound)
         return type.MakeArrayType(1);
     else if (_dimensions == 1)
         return type.MakeArrayType();
     return type.MakeArrayType(_dimensions);
 }
        private static object DeserializeArray(BinaryReader sourceReader, Type elementType, int elementSize, int elementCount)
        {
            var arrayDataAddress = sourceReader.BaseStream.Position;

            var fields = elementType.Fields(
                 Flags.Public |
                 Flags.NonPublic |
                 Flags.Instance);


            List<FieldDelegateInformation> fieldMethods;


            var item = elementType.CreateInstance();
            ProcessFieldTypes(fields, out fieldMethods);


            var array = elementType.MakeArrayType().CreateInstance(elementCount);

            for (var i = 0; i < elementCount; ++i)
            {
                var element = elementType.CreateInstance();
                sourceReader.BaseStream.Position = arrayDataAddress + i * elementSize;
                InvokeFields(sourceReader, element, fields, fieldMethods);
                array.SetElement(i, element);
            }
            return array;
        }
Example #6
0
		public static Type MakeArray (Type t, List<int> sizes, List<int> loBounds)
		{
			var mt = t as MetadataType;
			if (mt != null) {
				if (sizes == null) {
					sizes = new List<int> ();
					sizes.Add (1);
				}
				mt.m_arraySizes = sizes;
				mt.m_arrayLoBounds = loBounds;
				return mt;
			}
			if (sizes == null || sizes.Count == 1)
				return t.MakeArrayType ();
			return t.MakeArrayType (sizes.Capacity);
		}
Example #7
0
 /// <summary>
 /// Creates an array of the given type and stores it in a returned local.
 /// </summary>
 /// <param name="gen">The generator to inject the code into.</param>
 /// <param name="type">The type of the array.</param>
 /// <param name="size">The size of the array.</param>
 /// <returns>A local builder that now contains the array.</returns>
 public static LocalBuilder CreateArray(this ILGenerator gen, Type type, int size)
 {
     var ret = gen.DeclareLocal(type.MakeArrayType());
     gen.Emit(OpCodes.Ldc_I4, size);
     gen.Emit(OpCodes.Newarr, type);
     gen.Emit(OpCodes.Stloc, ret);
     return ret;
 }
        public static Type MakeArrayType(Type elementType)
        {
#if CF
            return Array.CreateInstance(elementType, 0).GetType(); // ouch
#else
            return elementType.MakeArrayType();
#endif
        }
        /// <summary>
        /// Builds <see cref="IArrayAccessor"/> for arrays with elements of type <paramref name="arrayElementType"/>.
        /// </summary>
        public static IArrayAccessor BuildForArrayOf(Type arrayElementType)
        {
            Guard.AgainstNull(arrayElementType, "arrayElementType");

            Type arrayType = arrayElementType.MakeArrayType();
            return new ArrayAccessor(arrayElementType, BuildGetMethod(arrayType, arrayElementType),
                BuildSetMethod(arrayType, arrayElementType));
        }
Example #10
0
        public static LocalBuilder CreateArray(this ILGenerator body, Type arrayType, int length)
        {
            var array = body.DeclareLocal(arrayType.MakeArrayType());
            body.Emit(OpCodes.Ldc_I4, length);
            body.Emit(OpCodes.Newarr, arrayType);
            body.Emit(OpCodes.Stloc, array);

            return array;
        }
Example #11
0
 Type EmitArrayInitializer(Type ElementType, CodeExpression Expr, int Index)
 {
     Generator.Emit(OpCodes.Dup);
     Generator.Emit(OpCodes.Ldc_I4, Index);
     Type Generated = EmitExpression(Expr);
     ForceTopStack(Generated, ElementType);
     Generator.Emit(OpCodes.Stelem_Ref);
     return ElementType.MakeArrayType();
 }
        protected virtual object StandardParse(string[] values, Type targetType, Type elementType)
        {
            var parser = StringParsing.GetParser(elementType);

            var arr = Activator.CreateInstance(elementType.MakeArrayType(), values.Count());
            for (var i = 0; i < values.Length; i++)
                ((Array)arr).SetValue(parser.Parse(values[i], elementType), i);

            return arr;
        }
		protected void CheckReturnTypeCanBeSatisfiedByArrayOf(Type type)
		{
			var arrayType = type.MakeArrayType();
			if (ComponentType.IsAssignableFrom(arrayType))
			{
				return;
			}

			ThrowUnsupportedCollectionType();
		}
        internal Type MakeElementTypes(Type type)
        {
            for (int i = m_elementTypes.Length - 1; i >= 0; i --)
            {
                if (m_elementTypes[i] == SzArray)
                {
                    type = type.MakeArrayType();
                }
                else if (m_elementTypes[i] == Array)
                {
                    type = type.MakeArrayType(m_elementTypes[--i]);
                }
                else if ((m_elementTypes[i] == Pointer))
                {
                    type = type.MakePointerType();
                }
                else if ((m_elementTypes[i] == ByRef))
                {
                    type = type.MakeByRefType();
                }
            }

            return type;
        }
Example #15
0
		public CastElement(ExpressionElement castExpression, string[] destTypeParts, bool isArray, IServiceProvider services)
		{
			MyCastExpression = castExpression;

			MyDestType = GetDestType(destTypeParts, services);

			if (MyDestType == null) {
				base.ThrowCompileException(CompileErrorResourceKeys.CouldNotResolveType, CompileExceptionReason.UndefinedName, GetDestTypeString(destTypeParts, isArray));
			}

			if (isArray == true) {
				MyDestType = MyDestType.MakeArrayType();
			}

			if (this.IsValidCast(MyCastExpression.ResultType, MyDestType) == false) {
				this.ThrowInvalidCastException();
			}
		}
Example #16
0
        /// <summary>
        /// Create the QM Func Source starting from a pre-parsed bunch of header info.
        /// </summary>
        /// <param name="f"></param>
        public QMFuncSource(QMFuncHeader f)
        {
            this._header = f;
            Name = "QMFunction".CreateUniqueVariableName();
            Arguments = f.Arguments.Select(a => new QMFunctionArgument(a));
            StatementBlock = null;

            // If this is a sequence, then we need to get a non-normal type.
            if (_header.IsSequence)
            {
                _sequenceType = _header.QM.GetResultType().GetGenericArguments().First();
                _sequenceType = _sequenceType.MakeArrayType();
            }

            // Now we can create the cached variables, etc.
            CacheVariable = DeclarableParameter.CreateDeclarableParameterExpression(ResultType);
            CacheVariableGood = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));

        }
Example #17
0
		static Type CreateArray (Type type, int rank)
		{
			return type.MakeArrayType (rank);
		}
Example #18
0
 private object lua_NewArray(Type typ, int len)
 {
     return Activator.CreateInstance(typ.MakeArrayType(), len);
 }
Example #19
0
        private static Array GetArrayObj(ParamValue propertyValue, Type type, string guid, out int dimensions,
            out Type arrayBaseType)
        {
            dimensions = type.FullName.Split(new[] { "[]" }, StringSplitOptions.None).Length - 1;
            arrayBaseType = type.GetElementType();
            for (int ii = 1; ii < dimensions; ii++)
            {
                arrayBaseType = arrayBaseType.GetElementType();
            }

            var parameterObject = arrayBaseType.MakeArrayType();

            for (int ii = 1; ii < dimensions; ii++)
            {
                parameterObject = parameterObject.MakeArrayType();
            }

            List<int> arrayIndexes = propertyValue.ArrayIndexes.Select(o => o.Int).ToList();

            Array aOo = Array.CreateInstance(arrayBaseType, arrayIndexes.ToArray());

            int i = 0;

            #region traverse array elements

            foreach (var lElement in propertyValue.ArrayElements)
            {
                object arrayElementObj = GetArrayElementObject(arrayBaseType, guid, lElement);

                List<int> indexes = new List<int>();

                for (int ir = 0; ir < arrayIndexes.Count; ir++)
                {
                    #region old logic, check if incorrect delete
                    //int tot = 0;
                    //for (int ri = arrayIndexes.Count - 1; ri > ir; ri--)
                    //{
                    //    tot += arrayIndexes[ri];
                    //}

                    //if (tot == 0)
                    //{
                    //    tot = arrayIndexes[arrayIndexes.Count - 1];
                    //}

                    //if (ir == arrayIndexes.Count - 1)
                    //{
                    //    indexes.Add(i%tot);
                    //}
                    //else
                    //{
                    //    indexes.Add(i/tot);
                    //}
                    #endregion

                    TestHelper.GetArrayIndexesFromLinearIndex(arrayIndexes, ir, indexes, i);
                }

                aOo.SetValue(arrayElementObj, indexes.ToArray());

                i++;
            }

            #endregion

            return aOo;
        }
Example #20
0
        /// <summary>
        /// Return instances of all registered types requested.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method is useful if you've registered multiple types with the same
        /// <see cref="Type"/> but different names.
        /// </para>
        /// <para>
        /// Be aware that this method does NOT return an instance for the default (unnamed) registration.
        /// </para>
        /// </remarks>
        /// <param name="t">The type requested.</param>
        /// <param name="resolverOverrides">Any overrides for the resolve calls.</param>
        /// <returns>Set of objects of type <paramref name="t"/>.</returns>
        public IEnumerable<object> ResolveAll(Type t, params ResolverOverride[] resolverOverrides)
        {
            Guard.ArgumentNotNull(t, "t");

            return (IEnumerable<object>)this.Resolve(t.MakeArrayType(), resolverOverrides);
        }
Example #21
0
        static Type fixType(TypeReference typeReference, Type type)
        {
            while (typeReference is TypeSpecification) {
                var ts = (TypeSpecification)typeReference;

                if (typeReference is ArrayType) {
                    var arrayType = (ArrayType)typeReference;
                    if (arrayType.IsVector)
                        type = type.MakeArrayType();
                    else
                        type = type.MakeArrayType(arrayType.Rank);
                }
                else if (typeReference is ByReferenceType) {
                    type = type.MakeByRefType();
                }
                else if (typeReference is PointerType) {
                    type = type.MakePointerType();
                }
                else if (typeReference is GenericInstanceType) {
                    var git = (GenericInstanceType)typeReference;
                    var args = new Type[git.GenericArguments.Count];
                    bool isGenericTypeDef = true;
                    for (int i = 0; i < args.Length; i++) {
                        var typeRef = git.GenericArguments[i];
                        if (!(typeRef.GetElementType() is GenericParameter))
                            isGenericTypeDef = false;
                        args[i] = Resolver.resolve(typeRef);
                    }
                    if (!isGenericTypeDef)
                        type = type.MakeGenericType(args);
                }

                typeReference = ts.ElementType;
            }
            return type;
        }
        public static string SetGenericArgumentType(string serializedTypeString, Type type)
        {
            if (!IsGeneric(serializedTypeString))
            {
                if (IsBaseTypeGeneric(serializedTypeString))
                {
                    throw new ArgumentException("Trying to set a different generic type. Reset old one first.");
                }
                throw new ArgumentException("Trying to set generic argument type for non generic type.");
            }
            SerializedTypeData data = SplitTypeString(serializedTypeString);
            data.genericTypeName = data.typeName;
            data.isGeneric = false;
            switch (data.typeName)
            {
                case "T":
                    data.typeName = ToShortTypeName(type);
                    break;

                case "T[]":
                    data.typeName = ToShortTypeName(type.MakeArrayType());
                    break;

                default:
                {
                    Type[] typeArguments = new Type[] { type };
                    data.typeName = ToShortTypeName(Type.GetType(data.typeName, true).GetGenericTypeDefinition().MakeGenericType(typeArguments));
                    break;
                }
            }
            return ToString(data);
        }
Example #23
0
        static CodeConditionStatement CreateArraySetValueCondition(Type type)
        {
            string lambda = type == typeof(decimal) ? "x => x.GetNumber()" :
                type == typeof(bool) ? "x => x.GetBool()" :
                type == typeof(string) ? "x => x.GetString()" :
                string.Format("x => ({0})x.GetNumber()", type.FullName);

            var toArray = CodeHelper
                .Arg("srcObj")
                .InvokeMethod("GetList")
                .InvokeMethod("Select",
                    new CodeSnippetExpression(lambda))
                .InvokeMethod("ToArray");
            return CreateSetValueCondition(type.MakeArrayType(), toArray);
        }
Example #24
0
        /// <summary>
        /// Creates a <see cref="NewArrayExpression"/> that represents creating an array that has a specified rank. 
        /// </summary>
        /// <param name="type">A <see cref="Type"/> that represents the element type of the array.</param>
        /// <param name="bounds">An IEnumerable{T} that contains Expression objects to use to populate the Expressions collection.</param>
        /// <returns>A <see cref="NewArrayExpression"/> that has the <see cref="P:NodeType"/> property equal to type and the <see cref="P:Expressions"/> property set to the specified value.</returns>
        public static NewArrayExpression NewArrayBounds(Type type, IEnumerable<Expression> bounds) {
            ContractUtils.RequiresNotNull(type, "type");
            ContractUtils.RequiresNotNull(bounds, "bounds");

            if (type.Equals(typeof(void))) {
                throw Error.ArgumentCannotBeOfTypeVoid();
            }

            ReadOnlyCollection<Expression> boundsList = bounds.ToReadOnly();

            int dimensions = boundsList.Count;
            if (dimensions <= 0) throw Error.BoundsCannotBeLessThanOne();

            for (int i = 0; i < dimensions; i++) {
                Expression expr = boundsList[i];
                RequiresCanRead(expr, "bounds");
                if (!TypeUtils.IsInteger(expr.Type)) {
                    throw Error.ArgumentMustBeInteger();
                }
            }

            Type arrayType;
            if (dimensions == 1) {
                //To get a vector, need call Type.MakeArrayType(). 
                //Type.MakeArrayType(1) gives a non-vector array, which will cause type check error.
                arrayType = type.MakeArrayType();
            } else {
                arrayType = type.MakeArrayType(dimensions);
            }

            return NewArrayExpression.Make(ExpressionType.NewArrayBounds, arrayType, bounds.ToReadOnly());
        }
Example #25
0
        /// <summary>
        /// Creates a new array expression of the specified type from the provided initializers.
        /// </summary>
        /// <param name="type">A Type that represents the element type of the array.</param>
        /// <param name="initializers">The expressions used to create the array elements.</param>
        /// <returns>An instance of the <see cref="NewArrayExpression"/>.</returns>
        public static NewArrayExpression NewArrayInit(Type type, IEnumerable<Expression> initializers) {
            ContractUtils.RequiresNotNull(type, "type");
            ContractUtils.RequiresNotNull(initializers, "initializers");
            if (type.Equals(typeof(void))) {
                throw Error.ArgumentCannotBeOfTypeVoid();
            }

            ReadOnlyCollection<Expression> initializerList = initializers.ToReadOnly();

            Expression[] newList = null;
            for (int i = 0, n = initializerList.Count; i < n; i++) {
                Expression expr = initializerList[i];
                RequiresCanRead(expr, "initializers");

                if (!TypeUtils.AreReferenceAssignable(type, expr.Type)) {
                    if (!TryQuote(type, ref expr)){
                        throw Error.ExpressionTypeCannotInitializeArrayType(expr.Type, type);
                    }
                    if (newList == null) {
                        newList = new Expression[initializerList.Count];
                        for (int j = 0; j < i; j++) {
                            newList[j] = initializerList[j];
                        }
                    }
                }
                if (newList != null) {
                    newList[i] = expr;
                }
            }
            if (newList != null) {
                initializerList = new TrueReadOnlyCollection<Expression>(newList);
            }

            return NewArrayExpression.Make(ExpressionType.NewArrayInit, type.MakeArrayType(), initializerList);
        }
Example #26
0
        /// <summary>
        /// Creates an array of the given type and stores it in a returned local.
        /// </summary>
        /// <param name="arrayType">The type of the array.</param>
        /// <param name="size">The size of the array.</param>
        /// <returns>A local builder that now contains the array.</returns>
        public LocalBuilder CreateArray(Type arrayType, int size)
        {
            var ret = CreateTemporary(arrayType.MakeArrayType());
            CurrentGenerator.Emit(OpCodes.Ldc_I4, size);
            CurrentGenerator.Emit(OpCodes.Newarr, arrayType);
            CurrentGenerator.Emit(OpCodes.Stloc, ret);

            return ret;
        }
Example #27
0
        /// <summary>
        /// Creates a new array of the specified element type.
        /// </summary>
        /// <param name="ilGenerator">The intermediate language generator.</param>
        /// <param name="elementType">The element type.</param>
        /// <param name="size">The array size.</param>
        /// <returns>The new array.</returns>
        public static LocalBuilder NewArray(this ILGenerator ilGenerator, Type elementType, int size)
        {
            if (ilGenerator == null)
                throw new ArgumentNullException("ilGenerator");

            if (elementType == null)
                throw new ArgumentNullException("elementType");

            var localBuilder = ilGenerator.DeclareLocal(elementType.MakeArrayType());

            ilGenerator.EmitLoadValue(size);
            ilGenerator.Emit(OpCodes.Newarr, elementType);
            ilGenerator.Emit(OpCodes.Stloc, localBuilder);

            return localBuilder;
        }
		ObjectWriter CreateWriter(Type type)
		{
			if (type == typeof(string)) {
				// String contents are written in the object creation section,
				// not into the field value section.
				return delegate {};
			}
			bool isArray = type.IsArray;
			if (isArray) {
				if (type.GetArrayRank() != 1)
					throw new NotSupportedException();
				type = type.GetElementType();
				if (!type.IsValueType) {
					return delegate (SerializationContext context, object array) {
						foreach (object val in (object[])array) {
							context.WriteObjectID(val);
						}
					};
				} else if (type == typeof(byte)) {
					return delegate (SerializationContext context, object array) {
						context.writer.Write((byte[])array);
					};
				}
			}
			List<FieldInfo> fields = GetSerializableFields(type);
			if (fields.Count == 0) {
				// The writer has nothing to do for this object.
				return delegate { };
			}
			
			
			DynamicMethod dynamicMethod = new DynamicMethod(
				(isArray ? "WriteArray_" : "Write_") + type.Name,
				typeof(void), new [] { typeof(SerializationContext), typeof(object) },
				true);
			ILGenerator il = dynamicMethod.GetILGenerator();
			
			var writer = il.DeclareLocal(typeof(BinaryWriter));
			
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Ldfld, writerField);
			il.Emit(OpCodes.Stloc, writer); // writer = context.writer;
			
			if (isArray) {
				var instance = il.DeclareLocal(type.MakeArrayType());
				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Castclass, type.MakeArrayType());
				il.Emit(OpCodes.Stloc, instance); // instance = (type[])arg_1;
				
				// for (int i = 0; i < instance.Length; i++) write instance[i];
				
				var loopStart = il.DefineLabel();
				var loopHead = il.DefineLabel();
				var loopVariable = il.DeclareLocal(typeof(int));
				il.Emit(OpCodes.Ldc_I4_0);
				il.Emit(OpCodes.Stloc, loopVariable); // loopVariable = 0
				il.Emit(OpCodes.Br, loopHead); // goto loopHead;
				
				il.MarkLabel(loopStart);
				
				if (type.IsEnum || type.IsPrimitive) {
					if (type.IsEnum) {
						type = type.GetEnumUnderlyingType();
					}
					Debug.Assert(type.IsPrimitive);
					il.Emit(OpCodes.Ldloc, writer); // writer
					il.Emit(OpCodes.Ldloc, instance); // writer, instance
					il.Emit(OpCodes.Ldloc, loopVariable); // writer, instance, loopVariable
					switch (Type.GetTypeCode(type)) {
						case TypeCode.Boolean:
						case TypeCode.SByte:
						case TypeCode.Byte:
							il.Emit(OpCodes.Ldelem_I1); // writer, instance[loopVariable]
							il.Emit(callVirt, writeByte); // writer.Write(instance[loopVariable]);
							break;
						case TypeCode.Char:
						case TypeCode.Int16:
						case TypeCode.UInt16:
							il.Emit(OpCodes.Ldelem_I2); // writer, instance[loopVariable]
							il.Emit(callVirt, writeShort); // writer.Write(instance[loopVariable]);
							break;
						case TypeCode.Int32:
						case TypeCode.UInt32:
							il.Emit(OpCodes.Ldelem_I4);  // writer, instance[loopVariable]
							il.Emit(callVirt, writeInt); // writer.Write(instance[loopVariable]);
							break;
						case TypeCode.Int64:
						case TypeCode.UInt64:
							il.Emit(OpCodes.Ldelem_I8);  // writer, instance[loopVariable]
							il.Emit(callVirt, writeLong); // writer.Write(instance[loopVariable]);
							break;
						case TypeCode.Single:
							il.Emit(OpCodes.Ldelem_R4);  // writer, instance[loopVariable]
							il.Emit(callVirt, writeFloat); // writer.Write(instance[loopVariable]);
							break;
						case TypeCode.Double:
							il.Emit(OpCodes.Ldelem_R8);  // writer, instance[loopVariable]
							il.Emit(callVirt, writeDouble); // writer.Write(instance[loopVariable]);
							break;
						default:
							throw new NotSupportedException("Unknown primitive type " + type);
					}
				} else {
					il.Emit(OpCodes.Ldloc, instance); // instance
					il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable
					il.Emit(OpCodes.Ldelem, type); // instance[loopVariable]
					EmitWriteValueType(il, writer, type);
				}
				
				il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable
				il.Emit(OpCodes.Ldc_I4_1); // loopVariable, 1
				il.Emit(OpCodes.Add); // loopVariable+1
				il.Emit(OpCodes.Stloc, loopVariable); // loopVariable++;
				
				il.MarkLabel(loopHead);
				il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable
				il.Emit(OpCodes.Ldloc, instance); // loopVariable, instance
				il.Emit(OpCodes.Ldlen); // loopVariable, instance.Length
				il.Emit(OpCodes.Conv_I4);
				il.Emit(OpCodes.Blt, loopStart); // if (loopVariable < instance.Length) goto loopStart;
			} else if (type.IsValueType) {
				// boxed value type
				if (type.IsEnum || type.IsPrimitive) {
					il.Emit(OpCodes.Ldloc, writer);
					il.Emit(OpCodes.Ldarg_1);
					il.Emit(OpCodes.Unbox_Any, type);
					WritePrimitiveValue(il, type);
				} else {
					il.Emit(OpCodes.Ldarg_1);
					il.Emit(OpCodes.Unbox_Any, type);
					EmitWriteValueType(il, writer, type);
				}
			} else {
				// reference type
				var instance = il.DeclareLocal(type);
				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Castclass, type);
				il.Emit(OpCodes.Stloc, instance); // instance = (type)arg_1;
				
				foreach (FieldInfo field in fields) {
					EmitWriteField(il, writer, instance, field); // write instance.Field
				}
			}
			il.Emit(OpCodes.Ret);
			return (ObjectWriter)dynamicMethod.CreateDelegate(typeof(ObjectWriter));
		}
		ObjectScanner CreateScanner(Type type)
		{
			bool isArray = type.IsArray;
			if (isArray) {
				if (type.GetArrayRank() != 1)
					throw new NotSupportedException();
				type = type.GetElementType();
				if (!type.IsValueType) {
					return delegate (SerializationContext context, object array) {
						foreach (object val in (object[])array) {
							context.Mark(val);
						}
					};
				}
			}
			for (Type baseType = type; baseType != null; baseType = baseType.BaseType) {
				if (!baseType.IsSerializable)
					throw new SerializationException("Type " + baseType + " is not [Serializable].");
			}
			List<FieldInfo> fields = GetSerializableFields(type);
			fields.RemoveAll(f => !IsReferenceOrContainsReferences(f.FieldType));
			if (fields.Count == 0) {
				// The scanner has nothing to do for this object.
				return delegate { };
			}
			
			DynamicMethod dynamicMethod = new DynamicMethod(
				(isArray ? "ScanArray_" : "Scan_") + type.Name,
				typeof(void), new [] { typeof(SerializationContext), typeof(object) },
				true);
			ILGenerator il = dynamicMethod.GetILGenerator();
			
			
			if (isArray) {
				var instance = il.DeclareLocal(type.MakeArrayType());
				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Castclass, type.MakeArrayType());
				il.Emit(OpCodes.Stloc, instance); // instance = (type[])arg_1;
				
				// for (int i = 0; i < instance.Length; i++) scan instance[i];
				var loopStart = il.DefineLabel();
				var loopHead = il.DefineLabel();
				var loopVariable = il.DeclareLocal(typeof(int));
				il.Emit(OpCodes.Ldc_I4_0);
				il.Emit(OpCodes.Stloc, loopVariable); // loopVariable = 0
				il.Emit(OpCodes.Br, loopHead); // goto loopHead;
				
				il.MarkLabel(loopStart);
				
				il.Emit(OpCodes.Ldloc, instance); // instance
				il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable
				il.Emit(OpCodes.Ldelem, type); // &instance[loopVariable]
				EmitScanValueType(il, type);
				
				
				il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable
				il.Emit(OpCodes.Ldc_I4_1); // loopVariable, 1
				il.Emit(OpCodes.Add); // loopVariable+1
				il.Emit(OpCodes.Stloc, loopVariable); // loopVariable++;
				
				il.MarkLabel(loopHead);
				il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable
				il.Emit(OpCodes.Ldloc, instance); // loopVariable, instance
				il.Emit(OpCodes.Ldlen); // loopVariable, instance.Length
				il.Emit(OpCodes.Conv_I4);
				il.Emit(OpCodes.Blt, loopStart); // if (loopVariable < instance.Length) goto loopStart;
			} else if (type.IsValueType) {
				// boxed value type
				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Unbox_Any, type);
				EmitScanValueType(il, type);
			} else {
				// reference type
				var instance = il.DeclareLocal(type);
				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Castclass, type);
				il.Emit(OpCodes.Stloc, instance); // instance = (type)arg_1;
				
				foreach (FieldInfo field in fields) {
					EmitScanField(il, instance, field); // scan instance.Field
				}
			}
			il.Emit(OpCodes.Ret);
			return (ObjectScanner)dynamicMethod.CreateDelegate(typeof(ObjectScanner));
		}
		ObjectReader CreateReader(Type type)
		{
			if (type == typeof(string)) {
				// String contents are written in the object creation section,
				// not into the field value section; so there's nothing to read here.
				return delegate {};
			}
			bool isArray = type.IsArray;
			if (isArray) {
				if (type.GetArrayRank() != 1)
					throw new NotSupportedException();
				type = type.GetElementType();
				if (!type.IsValueType) {
					return delegate (DeserializationContext context, object arrayInstance) {
						object[] array = (object[])arrayInstance;
						for (int i = 0; i < array.Length; i++) {
							array[i] = context.ReadObject();
						}
					};
				} else if (type == typeof(byte)) {
					return delegate (DeserializationContext context, object arrayInstance) {
						byte[] array = (byte[])arrayInstance;
						BinaryReader binaryReader = context.Reader;
						int pos = 0;
						int bytesRead;
						do {
							bytesRead = binaryReader.Read(array, pos, array.Length - pos);
							pos += bytesRead;
						} while (bytesRead > 0);
						if (pos != array.Length)
							throw new EndOfStreamException();
					};
				}
			}
			var fields = GetSerializableFields(type);
			if (fields.Count == 0) {
				// The reader has nothing to do for this object.
				return delegate { };
			}
			
			DynamicMethod dynamicMethod = new DynamicMethod(
				(isArray ? "ReadArray_" : "Read_") + type.Name,
				MethodAttributes.Public | MethodAttributes.Static,
				CallingConventions.Standard,
				typeof(void), new [] { typeof(DeserializationContext), typeof(object) },
				type,
				true);
			ILGenerator il = dynamicMethod.GetILGenerator();
			
			var reader = il.DeclareLocal(typeof(BinaryReader));
			
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Ldfld, readerField);
			il.Emit(OpCodes.Stloc, reader); // reader = context.reader;
			
			if (isArray) {
				var instance = il.DeclareLocal(type.MakeArrayType());
				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Castclass, type.MakeArrayType());
				il.Emit(OpCodes.Stloc, instance); // instance = (type[])arg_1;
				
				// for (int i = 0; i < instance.Length; i++) read &instance[i];
				
				var loopStart = il.DefineLabel();
				var loopHead = il.DefineLabel();
				var loopVariable = il.DeclareLocal(typeof(int));
				il.Emit(OpCodes.Ldc_I4_0);
				il.Emit(OpCodes.Stloc, loopVariable); // loopVariable = 0
				il.Emit(OpCodes.Br, loopHead); // goto loopHead;
				
				il.MarkLabel(loopStart);
				
				if (type.IsEnum || type.IsPrimitive) {
					if (type.IsEnum) {
						type = type.GetEnumUnderlyingType();
					}
					Debug.Assert(type.IsPrimitive);
					il.Emit(OpCodes.Ldloc, instance); // instance
					il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable
					ReadPrimitiveValue(il, reader, type); // instance, loopVariable, value
					switch (Type.GetTypeCode(type)) {
						case TypeCode.Boolean:
						case TypeCode.SByte:
						case TypeCode.Byte:
							il.Emit(OpCodes.Stelem_I1); // instance[loopVariable] = value;
							break;
						case TypeCode.Char:
						case TypeCode.Int16:
						case TypeCode.UInt16:
							il.Emit(OpCodes.Stelem_I2); // instance[loopVariable] = value;
							break;
						case TypeCode.Int32:
						case TypeCode.UInt32:
							il.Emit(OpCodes.Stelem_I4); // instance[loopVariable] = value;
							break;
						case TypeCode.Int64:
						case TypeCode.UInt64:
							il.Emit(OpCodes.Stelem_I8); // instance[loopVariable] = value;
							break;
						case TypeCode.Single:
							il.Emit(OpCodes.Stelem_R4); // instance[loopVariable] = value;
							break;
						case TypeCode.Double:
							il.Emit(OpCodes.Stelem_R8); // instance[loopVariable] = value;
							break;
						default:
							throw new NotSupportedException("Unknown primitive type " + type);
					}
				} else {
					il.Emit(OpCodes.Ldloc, instance); // instance
					il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable
					il.Emit(OpCodes.Ldelema, type); // instance[loopVariable]
					EmitReadValueType(il, reader, type);
				}
				
				il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable
				il.Emit(OpCodes.Ldc_I4_1); // loopVariable, 1
				il.Emit(OpCodes.Add); // loopVariable+1
				il.Emit(OpCodes.Stloc, loopVariable); // loopVariable++;
				
				il.MarkLabel(loopHead);
				il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable
				il.Emit(OpCodes.Ldloc, instance); // loopVariable, instance
				il.Emit(OpCodes.Ldlen); // loopVariable, instance.Length
				il.Emit(OpCodes.Conv_I4);
				il.Emit(OpCodes.Blt, loopStart); // if (loopVariable < instance.Length) goto loopStart;
			} else if (type.IsValueType) {
				// boxed value type
				il.Emit(OpCodes.Ldarg_1); // instance
				il.Emit(OpCodes.Unbox, type); // &(Type)instance
				if (type.IsEnum || type.IsPrimitive) {
					if (type.IsEnum) {
						type = type.GetEnumUnderlyingType();
					}
					Debug.Assert(type.IsPrimitive);
					ReadPrimitiveValue(il, reader, type); // &(Type)instance, value
					switch (Type.GetTypeCode(type)) {
						case TypeCode.Boolean:
						case TypeCode.SByte:
						case TypeCode.Byte:
							il.Emit(OpCodes.Stind_I1);
							break;
						case TypeCode.Char:
						case TypeCode.Int16:
						case TypeCode.UInt16:
							il.Emit(OpCodes.Stind_I2);
							break;
						case TypeCode.Int32:
						case TypeCode.UInt32:
							il.Emit(OpCodes.Stind_I4);
							break;
						case TypeCode.Int64:
						case TypeCode.UInt64:
							il.Emit(OpCodes.Stind_I8);
							break;
						case TypeCode.Single:
							il.Emit(OpCodes.Stind_R4);
							break;
						case TypeCode.Double:
							il.Emit(OpCodes.Stind_R8);
							break;
						default:
							throw new NotSupportedException("Unknown primitive type " + type);
					}
				} else {
					EmitReadValueType(il, reader, type);
				}
			} else {
				// reference type
				var instance = il.DeclareLocal(type);
				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Castclass, type);
				il.Emit(OpCodes.Stloc, instance); // instance = (type)arg_1;
				
				foreach (FieldInfo field in fields) {
					EmitReadField(il, reader, instance, field); // read instance.Field
				}
			}
			il.Emit(OpCodes.Ret);
			return (ObjectReader)dynamicMethod.CreateDelegate(typeof(ObjectReader));
		}