ICSharpCode.NRefactory.Utils.FastSerializer.CreateReader C# (CSharp) Method

CreateReader() private method

private CreateReader ( Type type ) : ObjectReader
type System.Type
return ObjectReader
		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));
		}