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

CreateScanner() private method

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