public void EmitDeserialize(PropertyInfo property, ref EmitHelper deserializeEmit)
		{
			var propertyType = property.PropertyType;
			var propertyNullLabel = deserializeEmit.DefineLabel();
			var propertyNotNullLabel = deserializeEmit.DefineLabel();
			var propertyInstanceType = deserializeEmit.DeclareLocal(typeof(Type));
			var indexLocal = deserializeEmit.DeclareLocal(typeof(int));
			var objectExistsLocal = deserializeEmit.DefineLabel();
			var objectNotExistsLocal = deserializeEmit.DefineLabel();
			deserializeEmit
				.ldarg_1
				.call(typeof(BinaryReader).GetMethod("ReadInt32"))
				.stloc(indexLocal)
				.ldloc(indexLocal)
				.ldc_i4_m1
				.ceq
				.brfalse(propertyNotNullLabel)
				.ldarg_0
				.ldnull
				.call(property.GetSetMethod())
				.br(propertyNullLabel)
				.MarkLabel(propertyNotNullLabel)
				.ldarg_2
				.ldloc(indexLocal)
				.call(typeof(IDictionary<int, object>).GetMethod("ContainsKey", new Type[] { typeof(int) }))
				.brfalse(objectNotExistsLocal)
				.ldarg_0
				.ldarg_2
				.ldloc(indexLocal)
				.call(typeof(IDictionary<int, object>).GetMethod("get_Item", new Type[] { typeof(int) }))
				.castclass(propertyType)
				.call(property.GetSetMethod())
				.br(objectExistsLocal)
				.MarkLabel(objectNotExistsLocal)
				.ldarg_1
				.call(typeof(BinaryReader).GetMethod("ReadString"))
				.call(typeof(Type).GetMethod("GetType", new Type[] { typeof(string) }))
				.stloc(propertyInstanceType)
				.ldarg_0
				.ldloc(propertyInstanceType)
				.call(typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type) }))
				.call(typeof(Converter).GetMethod("Convert", new[] { typeof(object) }))
				.castclass(propertyType)
				.call(property.GetSetMethod())
				.ldarg_2
				.ldloc(indexLocal)
				.ldarg_0
				.call(property.GetGetMethod())
				.call(typeof(IDictionary<int, object>).GetMethod("Add", new[] { typeof(int), typeof(object) }))
				.ldarg_0
				.call(property.GetGetMethod())
				.castclass(typeof(ISerializable))
				.ldarg_1
				.ldarg_2
				.call(typeof(ISerializable).GetMethod("Deserialize", new Type[] { typeof(BinaryReader), typeof(IDictionary<int, object>) }))
				.MarkLabel(objectExistsLocal)
				.MarkLabel(propertyNullLabel);
		}
		public void EmitSerialize(PropertyInfo property, ref EmitHelper serializerEmit)
		{
			var obj = serializerEmit.DeclareLocal(typeof(object));
			var propertyNullLabel = serializerEmit.DefineLabel();
			var propertyNotNullLabel = serializerEmit.DefineLabel();
			var objectExistsLocal = serializerEmit.DefineLabel();
			var objectNotExistsLocal = serializerEmit.DefineLabel();
			serializerEmit
				.ldarg_0
				.call(property.GetGetMethod())
				.stloc(obj)
				.ldloc(obj)
				.brtrue(propertyNotNullLabel)
				.ldarg_1
				.ldc_i4_m1
				.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
				.br(propertyNullLabel)
				.MarkLabel(propertyNotNullLabel)
				.ldarg_2
				.ldloc(obj)
				.call(typeof(IDictionary<object, int>).GetMethod("ContainsKey", new[] { typeof(object) }))
				.brtrue(objectExistsLocal)
				.ldarg_1
				.ldarg_3
				.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
				.ldloc(obj)
				.castclass(typeof(ISerializable))
				.ldarg_1
				.ldarg_2
				.ldarg_3
				.call(typeof(ISerializable).GetMethod("Serialize"))
				.br(objectNotExistsLocal)
				.MarkLabel(objectExistsLocal)
				.ldarg_1
				.ldarg_2
				.ldloc(obj)
				.call(typeof(IDictionary<object, int>).GetMethod("get_Item", new[] { typeof(object) }))
				.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
				.MarkLabel(objectNotExistsLocal)
				.MarkLabel(propertyNullLabel);
		}
		private void CreateInitContextDefaultInstance(
			string       initContextName,
			FieldBuilder field,
			TypeHelper   fieldType,
			TypeHelper   objectType,
			EmitHelper   emit,
			object[]     parameters)
		{
			if (!CheckObjectHolderCtor(fieldType, objectType))
				return;

			LocalBuilder initField    = GetInitContextBuilder(initContextName, emit);
			MethodInfo   memberParams = InitContextType.GetProperty("MemberParameters").GetSetMethod();

			if (parameters != null)
			{
				emit
					.ldloc    (initField)
					.ldsfld   (GetParameterField())
					.callvirt (memberParams)
					;
			}
			else if ((bool)Context.Items["$BLToolkit.Default.DirtyParameters"])
			{
				emit
					.ldloc    (initField)
					.ldnull
					.callvirt (memberParams)
					;
			}

			Context.Items["$BLToolkit.Default.DirtyParameters"] = parameters != null;

			if (objectType.IsAbstract)
			{
				emit
					.ldarg_0
					.ldsfld             (GetTypeAccessorField())
					.ldloc              (initField)
					.callvirtNoGenerics (typeof(TypeAccessor), "CreateInstanceEx", _initContextType)
					.isinst             (objectType)
					;
			}
			else
			{
				emit
					.ldarg_0
					.ldloc   (initField)
					.newobj  (objectType.GetPublicConstructor(typeof(InitContext)))
					;
			}

			if (IsObjectHolder)
			{
				emit
					.newobj (fieldType, objectType)
					;
			}

			emit
				.stfld (field)
				;
		}
		private void CreateAbstractInitContextInstance(
			FieldBuilder field, TypeHelper fieldType, TypeHelper objectType, EmitHelper emit, object[] parameters)
		{
			if (!CheckObjectHolderCtor(fieldType, objectType))
				return;

			MethodInfo memberParams = InitContextType.GetProperty("MemberParameters").GetSetMethod();

			LocalBuilder parentField = (LocalBuilder)Context.Items["$BLToolkit.InitContext.Parent"];

			if (parentField == null)
			{
				Context.Items["$BLToolkit.InitContext.Parent"] = parentField = emit.DeclareLocal(typeof(object));

				Label label = emit.DefineLabel();

				emit
					.ldarg_1
					.brtrue_s  (label)

					.newobj    (InitContextType.GetPublicDefaultConstructor())
					.starg     (1)

					.ldarg_1
					.ldc_i4_1
					.callvirt  (InitContextType.GetProperty("IsInternal").GetSetMethod())

					.MarkLabel (label)

					.ldarg_1
					.callvirt  (InitContextType.GetProperty("Parent").GetGetMethod())
					.stloc     (parentField)
					;
			}

			emit
				.ldarg_1
				.ldarg_0
				.callvirt (InitContextType.GetProperty("Parent").GetSetMethod())
				;

			object isDirty = Context.Items["$BLToolkit.InitContext.DirtyParameters"];

			if (parameters != null)
			{
				emit
					.ldarg_1
					.ldsfld   (GetParameterField())
					.callvirt (memberParams)
					;
			}
			else if (isDirty != null && (bool)isDirty)
			{
				emit
					.ldarg_1
					.ldnull
					.callvirt (memberParams)
					;
			}

			Context.Items["$BLToolkit.InitContext.DirtyParameters"] = parameters != null;

			if (objectType.IsAbstract)
			{
				emit
					.ldarg_0
					.ldsfld             (GetTypeAccessorField())
					.ldarg_1
					.callvirtNoGenerics (typeof(TypeAccessor), "CreateInstanceEx", _initContextType)
					.isinst             (objectType)
					;
			}
			else
			{
				emit
					.ldarg_0
					.ldarg_1
					.newobj  (objectType.GetPublicConstructor(typeof(InitContext)))
					;
			}

			if (IsObjectHolder)
			{
				emit
					.newobj (fieldType, objectType)
					;
			}

			emit
				.stfld (field)
				;
		}
		private void CreateParametrizedInstance(
			FieldBuilder field, TypeHelper fieldType, TypeHelper objectType, EmitHelper emit, object[] parameters)
		{
			if (!CheckObjectHolderCtor(fieldType, objectType))
				return;

			if (parameters.Length == 1)
			{
				object o = parameters[0];

				if (o == null)
				{
					if (objectType.IsValueType == false)
						emit
							.ldarg_0
							.ldnull
							.end()
							;

					if (IsObjectHolder)
					{
						emit
							.newobj (fieldType, objectType)
							;
					}

					emit
						.stfld (field)
						;

					return;
				}
				else
				{
					if (objectType.Type == o.GetType())
					{
						if (objectType.Type == typeof(string))
						{
							emit
								.ldarg_0
								.ldstr   ((string)o)
								.stfld   (field)
								;

							return;
						}

						if (objectType.IsValueType)
						{
							emit.ldarg_0.end();

							if (emit.LoadWellKnownValue(o) == false)
							{
								emit
									.ldsfld     (GetParameterField())
									.ldc_i4_0
									.ldelem_ref
									.end()
									;
							}

							emit.stfld(field);

							return;
						}
					}
				}
			}

			Type[] types = new Type[parameters.Length];

			for (int i = 0; i < parameters.Length; i++)
			{
				if (parameters[i] != null)
				{
					Type t = parameters[i].GetType();

					types[i] = (t.IsEnum) ? Enum.GetUnderlyingType(t) : t;
				}
				else
					types[i] = typeof(object);
			}

			ConstructorInfo ci = objectType.GetPublicConstructor(types);

			if (ci == null)
			{
				if (objectType.IsValueType)
					return;

				throw new TypeBuilderException(
					string.Format(types.Length == 0?
							Resources.TypeBuilder_PropertyTypeHasNoPublicDefaultCtor:
							Resources.TypeBuilder_PropertyTypeHasNoPublicCtor,
						Context.CurrentProperty.Name,
						Context.Type.FullName,
						objectType.FullName));
			}

			ParameterInfo[] pi = ci.GetParameters();

			emit.ldarg_0.end();

			for (int i = 0; i < parameters.Length; i++)
			{
				object o     = parameters[i];
				Type   oType = o.GetType();

				if (emit.LoadWellKnownValue(o))
				{
					if (oType.IsValueType)
					{
						if (!pi[i].ParameterType.IsValueType)
							emit.box(oType);
						else if (Type.GetTypeCode(oType) != Type.GetTypeCode(pi[i].ParameterType))
							emit.conv(pi[i].ParameterType);
					}
				}
				else
				{
					emit
						.ldsfld         (GetParameterField())
						.ldc_i4         (i)
						.ldelem_ref
						.CastFromObject (types[i])
						;

					if (oType.IsValueType && !pi[i].ParameterType.IsValueType)
						emit.box(oType);
				}
			}

			emit
				.newobj (ci)
				;

			if (IsObjectHolder)
			{
				emit
					.newobj (fieldType, objectType)
					;
			}

			emit
				.stfld  (field)
				;
		}
		private void CreateDefaultInstance(
			FieldBuilder field, TypeHelper fieldType, TypeHelper objectType, EmitHelper emit)
		{
			if (!CheckObjectHolderCtor(fieldType, objectType))
				return;

			if (objectType.Type == typeof(string))
			{
				emit
					.ldarg_0
					.LoadInitValue (objectType)
					;
			}
			else if (objectType.IsArray)
			{
				FieldBuilder initializer = GetArrayInitializer(objectType);

				emit
					.ldarg_0
					.ldsfld  (initializer)
					;
			}
			else
			{
				ConstructorInfo ci = objectType.GetPublicDefaultConstructor();

				if (ci == null)
				{
					if (objectType.Type.IsValueType)
						return;

					string message = string.Format(
						Resources.TypeBuilder_PropertyTypeHasNoPublicDefaultCtor,
						Context.CurrentProperty.Name,
						Context.Type.FullName,
						objectType.FullName);

					emit
						.ldstr  (message)
						.newobj (typeof(TypeBuilderException), typeof(string))
						.@throw
						.end()
						;

					return;
				}
				else
				{
					emit
						.ldarg_0
						.newobj  (ci)
						;
				}
			}

			if (IsObjectHolder)
			{
				emit
					.newobj (fieldType, objectType)
					;
			}

			emit
				.stfld (field)
				;
		}
		public void Emit(FieldInfo field, ref EmitHelper serializerEmit, ref EmitHelper deserializeEmit)
		{
			var fieldType = field.FieldType;
			var writeIntMethod = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) });
			var dictNotNullLabel = serializerEmit.DefineLabel();
			var dictNullLabel = serializerEmit.DefineLabel();
			var keyType = fieldType.GetGenericArguments()[0];
			if (!keyType.IsPrimitive && !(keyType == typeof(DateTime)) && !(keyType == typeof(string)) && !(keyType == typeof(decimal)))
			{
				throw new ArgumentException("Key type does not supported: " + keyType);
			}
			var valueType = fieldType.GetGenericArguments()[1];
			if (!valueType.IsPrimitive && !(valueType == typeof(DateTime)) && !(valueType == typeof(string)) && !(valueType == typeof(decimal)))
			{
				throw new ArgumentException("Value type does not supported: " + valueType);
			}
			var dictLocal = serializerEmit.DeclareLocal(fieldType);
			//construct ICollection<elementType> to call getCount method
			var keyValuePairType = typeof(KeyValuePair<,>);
			keyValuePairType = keyValuePairType.MakeGenericType(keyType, valueType);
			var getKeyMethod = keyValuePairType.GetMethod("get_Key");
			var getValueMethod = keyValuePairType.GetMethod("get_Value");
			var icollectionType = typeof(ICollection<>).MakeGenericType(keyValuePairType);
			var getCountMethod = icollectionType.GetMethod("get_Count");
			var enumeratorType = typeof(IEnumerator<>).MakeGenericType(keyValuePairType);
			var getEmumeratorMethod = typeof(IEnumerable<>).MakeGenericType(keyValuePairType).GetMethod("GetEnumerator");
			var getCurrentElementMethod = enumeratorType.GetMethod("get_Current");
			var keyValuePairLocal = serializerEmit.DeclareLocal(keyValuePairType);
			var enumeratorLocal = serializerEmit.DeclareLocal(enumeratorType);
			var startWhileLocal = serializerEmit.DefineLabel();
			var startWhileBodyLocal = serializerEmit.DefineLabel();
			var valueLocal = serializerEmit.DeclareLocal(valueType);
			var endFinallyLabel = serializerEmit.DefineLabel();
			serializerEmit
				.ldarg_0
				.ldfld(field)
				.stloc(dictLocal)
				.ldloc(dictLocal)
				.brtrue(dictNotNullLabel)
				.ldarg_1
				.ldc_i4_m1
				.call(writeIntMethod)
				.br(dictNullLabel)
				.MarkLabel(dictNotNullLabel);
			var exTryCatchFinallyLabel = serializerEmit.BeginExceptionBlock();
			serializerEmit
				.ldloc(dictLocal)
				.call(getEmumeratorMethod)
				.stloc(enumeratorLocal)
				.ldarg_1
				.ldloc(dictLocal)
				.call(getCountMethod)
				.call(writeIntMethod)
				.br(startWhileLocal)
				.MarkLabel(startWhileBodyLocal)
				.ldloc(enumeratorLocal)
				.call(getCurrentElementMethod)
				.stloc(keyValuePairLocal)
				.ldarg_1
				.ldloca(keyValuePairLocal)
				.call(getKeyMethod)
				.call(typeof(BinaryWriter).GetMethod("Write", new[] { keyType }));
			if (valueType == typeof(string))
			{
				var valueLocalNotNullLabel = serializerEmit.DefineLabel();
				var valueLocalNullLabel = serializerEmit.DefineLabel();
				serializerEmit
					.ldloca(keyValuePairLocal)
					.call(getValueMethod)
					.stloc(valueLocal)
					.ldloc(valueLocal)
					.brtrue(valueLocalNotNullLabel)
					.ldarg_1
					.ldc_i4_m1
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.br(valueLocalNullLabel)
					.MarkLabel(valueLocalNotNullLabel)
					.ldarg_1
					.ldloc(valueLocal)
					.call(typeof(string).GetMethod("get_Length"))
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.ldarg_1
					.ldloc(valueLocal)
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(string) }))
					.MarkLabel(valueLocalNullLabel);
			}
			else if (valueType.IsPrimitive)
			{
				serializerEmit
					.ldarg_1
					.ldloca(keyValuePairLocal)
					.call(getValueMethod)
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { valueType }));
			}
			serializerEmit
				.MarkLabel(startWhileLocal)
				.ldloc(enumeratorLocal)
				.call(typeof(IEnumerator).GetMethod("MoveNext"))
				.brtrue(startWhileBodyLocal)
				.leave(exTryCatchFinallyLabel)
				.BeginFinallyBlock()
				.ldloc(enumeratorLocal)
				.brfalse(endFinallyLabel)
				.ldloc(enumeratorLocal)
				.call(typeof(IDisposable).GetMethod("Dispose"))
				.MarkLabel(endFinallyLabel)
				.EndExceptionBlock()
				.MarkLabel(dictNullLabel);

			var readIntMethod = typeof(BinaryReader).GetMethod("ReadInt32");
			var addElementMethod = typeof(IDictionary<,>).MakeGenericType(keyType, valueType).GetMethod("Add", new[] { keyType, valueType });
			var dictNotNullLabel2 = deserializeEmit.DefineLabel();
			var dictNullLabel2 = deserializeEmit.DefineLabel();
			var deserializeDictLocal = deserializeEmit.DeclareLocal(fieldType);
			var len = deserializeEmit.DeclareLocal(typeof(int));
			var i = deserializeEmit.DeclareLocal(typeof(int));
			var beginForLabel = deserializeEmit.DefineLabel();
			var beginForBodyLabel = deserializeEmit.DefineLabel();

			var dictType = fieldType.IsInterface ? typeof(Dictionary<,>).MakeGenericType(keyType, valueType) : fieldType;
			var keyLocal = deserializeEmit.DeclareLocal(keyType);
			var valueLocal2 = deserializeEmit.DeclareLocal(valueType);

			deserializeEmit = deserializeEmit
				.ldarg_1
				.call(readIntMethod)
				.stloc(len)
				.ldloc(len)
				.ldc_i4_m1
				.ceq
				.brfalse(dictNotNullLabel2)
				.ldarg_0
				.ldnull
				.stfld(field)
				.br(dictNullLabel2)
				.MarkLabel(dictNotNullLabel2)
				.ldloc(len)
				.newobj(dictType, typeof(int))
				.stloc(deserializeDictLocal)
				.ldc_i4_0
				.stloc(i)
				.br(beginForLabel)
				.MarkLabel(beginForBodyLabel);
			if (keyType.IsPrimitive || keyType == typeof(decimal))
			{
				deserializeEmit
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("Read" + keyType.Name))
					.stloc(keyLocal);
			}
			else if (keyType == typeof(DateTime))
			{
				deserializeEmit
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadInt64"))
					.newobj(typeof(DateTime), typeof(long))
					.stloc(keyLocal);
			}
			else if (keyType == typeof(string))
			{
				deserializeEmit
					.ldloca(keyLocal)
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadString"))
					.stobj(typeof(string));
			}
			if (valueType.IsPrimitive || valueType == typeof(decimal))
			{
				deserializeEmit
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("Read" + keyType.Name))
					.stloc(valueLocal2);
			}
			else if (valueType == typeof(DateTime))
			{
				deserializeEmit
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadInt64"))
					.newobj(typeof(DateTime), typeof(long))
					.stloc(valueLocal2);
			}
			else if (valueType == typeof(string))
			{
				var strNullLabel = deserializeEmit.DefineLabel();
				var strNotNullLabel = deserializeEmit.DefineLabel();
				deserializeEmit
					.ldarg_1
					.call(readIntMethod)
					.ldc_i4_m1
					.ceq
					.brfalse(strNotNullLabel)
					.ldnull
					.stloc(valueLocal2)
					.br(strNullLabel)
					.MarkLabel(strNotNullLabel)
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadString"))
					.stloc(valueLocal2)
					.MarkLabel(strNullLabel);
			}
			deserializeEmit
				.ldloc(deserializeDictLocal)
				.ldloc(keyLocal)
				.ldloc(valueLocal2)
				.call(addElementMethod)
				.ldloc(i)
				.ldc_i4_1
				.add
				.stloc(i)
				.MarkLabel(beginForLabel)
				.ldloc(i)
				.ldloc(len)
				.clt
				.brtrue(beginForBodyLabel)
				.ldarg_0
				.ldloc(deserializeDictLocal)
				.stfld(field)
				.MarkLabel(dictNullLabel2);
		}
		public void Emit(FieldInfo field, ref EmitHelper serializerEmit, ref EmitHelper deserializeEmit)
		{
			var fieldType = field.FieldType;
			var writeStringMethod = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(string) });
			var writeIntMethod = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) });
			var listNotNullLabel = serializerEmit.DefineLabel();
			var listNullLabel = serializerEmit.DefineLabel();
			var whileLabel = serializerEmit.DefineLabel();
			var endWhileLabel = serializerEmit.DefineLabel();
			var elementType = fieldType.GetGenericArguments()[0];
			var iLocal = serializerEmit.DeclareLocal(typeof(int));
			var lenLocal = serializerEmit.DeclareLocal(typeof(int));
			//construct ICollection<elementType> to call getCount method
			var icollectionType = typeof(ICollection<>).MakeGenericType(elementType);
			var getCountMethod = icollectionType.GetMethod("get_Count");
			serializerEmit
				.ldarg_0
				.ldfld(field)
				.brtrue(listNotNullLabel)
				.ldarg_1
				.ldc_i4_m1
				.call(writeIntMethod)
				.br(listNullLabel)
				.MarkLabel(listNotNullLabel)
				.ldc_i4_0
				.stloc(iLocal)
				.ldarg_0
				.ldfld(field)
				.call(getCountMethod)
				.stloc(lenLocal)
				.ldarg_1
				.ldloc(lenLocal)
				.call(writeIntMethod)
				.br(endWhileLabel)
				.MarkLabel(whileLabel);
			if (elementType == typeof(string))
			{
				var strElement = serializerEmit.DeclareLocal(typeof(string));
				var strElementNullLbl = serializerEmit.DefineLabel();
				var strElementNotNullLbl = serializerEmit.DefineLabel();
				serializerEmit
					.ldarg_0
					.ldfld(field)
					.ldloc(iLocal)
					.call(fieldType.GetMethod("get_Item"))
					.stloc(strElement)
					.ldloc(strElement)
					.brtrue(strElementNotNullLbl)
					.ldarg_1
					.ldc_i4_m1
					.call(writeIntMethod)
					.br(strElementNullLbl)
					.MarkLabel(strElementNotNullLbl)
					.ldarg_1
					.ldloc(strElement)
					.call(typeof(string).GetMethod("get_Length"))
					.call(writeIntMethod)
					.ldarg_1
					.ldloc(strElement)
					.call(writeStringMethod)
					.MarkLabel(strElementNullLbl)
					.ldloc(iLocal)
					.ldc_i4_1
					.add
					.stloc(iLocal);
			}
			else if (elementType.IsPrimitive || elementType == typeof(DateTime) || elementType == typeof(decimal))
			{
				serializerEmit
					.ldarg_1
					.ldarg_0
					.ldfld(field)
					.ldloc(iLocal)
					.dup
					.ldc_i4_1
					.add
					.stloc(iLocal)
					.call(fieldType.GetMethod("get_Item"));
				var writeElementType = elementType != typeof(DateTime) ? elementType : typeof(long);
				serializerEmit
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { writeElementType }));
			}
			else if (elementType.IsClass)
			{
				var obj = serializerEmit.DeclareLocal(typeof(object));
				var elementNullLabel = serializerEmit.DefineLabel();
				var elementNotNullLabel = serializerEmit.DefineLabel();
				var objectExistsLocal = serializerEmit.DefineLabel();
				var objectNotExistsLocal = serializerEmit.DefineLabel();
				serializerEmit
					.ldarg_0
					.ldfld(field)
					.ldloc(iLocal)
					.call(fieldType.GetMethod("get_Item"))
					.stloc(obj)
					.ldloc(obj)
					.brtrue(elementNotNullLabel)
					.ldarg_1
					.ldc_i4_m1
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.br(elementNullLabel)
					.MarkLabel(elementNotNullLabel)
					.ldarg_2
					.ldloc(obj)
					.call(typeof(IDictionary<object, int>).GetMethod("ContainsKey", new[] { typeof(object) }))
					.brtrue(objectExistsLocal)
					.ldarg_1
					.ldarg_3
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.ldloc(obj)
					.castclass(typeof(ISerializable))
					.ldarg_1
					.ldarg_2
					.ldarg_3
					.call(typeof(ISerializable).GetMethod("Serialize"))
					.br(objectNotExistsLocal)
					.MarkLabel(objectExistsLocal)
					.ldarg_1
					.ldarg_2
					.ldloc(obj)
					.call(typeof(IDictionary<object, int>).GetMethod("get_Item", new[] { typeof(object) }))
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.MarkLabel(objectNotExistsLocal)
					.MarkLabel(elementNullLabel)
					.ldloc(iLocal)
					.ldc_i4_1
					.add
					.stloc(iLocal);
			}
			else
			{
				throw new ArgumentException("Element type does not supported: " + elementType);
			}
			serializerEmit
				.MarkLabel(endWhileLabel)
				.ldloc(iLocal)
				.ldloc(lenLocal)
				.blt(whileLabel)
				.MarkLabel(listNullLabel);

			var readIntMethod = typeof(BinaryReader).GetMethod("ReadInt32");
			var addElementMethod = typeof(ICollection<>).MakeGenericType(elementType).GetMethod("Add");
			var listNotNullLabel2 = deserializeEmit.DefineLabel();
			var listNullLabel2 = deserializeEmit.DefineLabel();
			var listLocal = deserializeEmit.DeclareLocal(fieldType);
			var len = deserializeEmit.DeclareLocal(typeof(int));
			var i = deserializeEmit.DeclareLocal(typeof(int));
			var beginForLabel = deserializeEmit.DefineLabel();
			var beginForBodyLabel = deserializeEmit.DefineLabel();
			var listType = fieldType.IsInterface ? typeof(List<>).MakeGenericType(elementType) : fieldType;
			deserializeEmit = deserializeEmit
				.ldarg_1
				.call(readIntMethod)
				.stloc(len)
				.ldloc(len)
				.ldc_i4_m1
				.ceq
				.brfalse(listNotNullLabel2)
				.ldarg_0
				.ldnull
				.stfld(field)
				.br(listNullLabel2)
				.MarkLabel(listNotNullLabel2)
				.ldloc(len)
				.newobj(listType, typeof(int))
				.stloc(listLocal)
				.ldc_i4_0
				.stloc(i)
				.br(beginForLabel)
				.MarkLabel(beginForBodyLabel);
			if (elementType.IsPrimitive)
			{
				deserializeEmit
					.ldloc(listLocal)
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("Read" + elementType.Name))
					.call(addElementMethod);
			}
			else if (elementType == typeof(DateTime))
			{
				deserializeEmit
					.ldloc(listLocal)
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadInt64"))
					.newobj(typeof(DateTime), typeof(long))
					.call(addElementMethod);
			}
			else if (elementType == typeof(string))
			{
				var strLen = deserializeEmit.DeclareLocal(typeof(int));
				var strNullLabel = deserializeEmit.DefineLabel();
				var strNotNullLabel = deserializeEmit.DefineLabel();
				deserializeEmit
					.ldarg_1
					.call(readIntMethod)
					.stloc(strLen)
					.ldloc(strLen)
					.ldc_i4_m1
					.ceq
					.brfalse(strNotNullLabel)
					.ldloc(listLocal)
					.ldnull
					.call(addElementMethod)
					.br(strNullLabel)
					.MarkLabel(strNotNullLabel)
					.ldloc(listLocal)
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadString"))
					.call(addElementMethod)
					.MarkLabel(strNullLabel);
			}
			else if (elementType.IsClass)
			{
				var desElementNullLabel = deserializeEmit.DefineLabel();
				var desElementNotNullLabel = deserializeEmit.DefineLabel();
				var propertyInstanceType = deserializeEmit.DeclareLocal(typeof(Type));
				var indexLocal = deserializeEmit.DeclareLocal(typeof(int));
				var desobjectExistsLocal = deserializeEmit.DefineLabel();
				var desobjectNotExistsLocal = deserializeEmit.DefineLabel();
				var tmpObjectLocal = deserializeEmit.DeclareLocal(elementType);
				var desTypeName = deserializeEmit.DeclareLocal(typeof(string));
				deserializeEmit
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadInt32"))
					.stloc(indexLocal)
					.ldloc(indexLocal)
					.ldc_i4_m1
					.ceq
					.brfalse(desElementNotNullLabel)
					.ldloc(listLocal)
					.ldnull
					.call(addElementMethod)
					.br(desElementNullLabel)
					.MarkLabel(desElementNotNullLabel)
					.ldarg_2
					.ldloc(indexLocal)
					.call(typeof(IDictionary<int, object>).GetMethod("ContainsKey", new Type[] { typeof(int) }))
					.brfalse(desobjectNotExistsLocal)
					.ldloc(listLocal)
					.ldarg_2
					.ldloc(indexLocal)
					.callvirt(typeof(IDictionary<int, object>).GetMethod("get_Item", new Type[] { typeof(int) }))
					.castclass(elementType)
					.call(addElementMethod)
					.br(desobjectExistsLocal)
					.MarkLabel(desobjectNotExistsLocal)
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadString"))
					.stloc(desTypeName)
					.ldloc(desTypeName)
					.ldc_i4_1
					.call(typeof(Type).GetMethod("GetType", new Type[] { typeof(string), typeof(bool) }))
					.stloc(propertyInstanceType)
					.ldloc(propertyInstanceType)
					.call(typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type) }))
					.castclass(elementType)
					.stloc(tmpObjectLocal)
					.ldarg_2
					.ldloc(indexLocal)
					.ldloc(tmpObjectLocal)
					.call(typeof(IDictionary<int, object>).GetMethod("Add", new[] { typeof(int), typeof(object) }))
					.ldloc(tmpObjectLocal)
					.castclass(typeof(ISerializable))
					.ldarg_1
					.ldarg_2
					.call(typeof(ISerializable).GetMethod("Deserialize",
														   new Type[] { typeof(BinaryReader), typeof(IDictionary<int, object>) }))
					.ldloc(listLocal)
					.ldloc(tmpObjectLocal)
					.call(addElementMethod)
					.MarkLabel(desobjectExistsLocal)
					.MarkLabel(desElementNullLabel);
			}
			deserializeEmit
				.ldloc(i)
				.ldc_i4_1
				.add
				.stloc(i)
				.MarkLabel(beginForLabel)
				.ldloc(i)
				.ldloc(len)
				.clt
				.brtrue(beginForBodyLabel)
				.ldarg_0
				.ldloc(listLocal)
				.stfld(field)
				.MarkLabel(listNullLabel2);
		}
		private void EmitCookie(EmitHelper emit)
		{
			string fieldName = "_cookie$" + Context.CurrentMethod.Name;

			FieldBuilder field = Context.GetField(fieldName) ??
				Context.CreateField(fieldName, typeof(AsyncCallState), FieldAttributes.Private);

			Label checkCookie = emit.DefineLabel();

			emit
				.ldarg_0
				.ldfld      (field)
				.dup
				.brtrue_s   (checkCookie)
				.pop
				.ldarg_0
				.dup
				.newobj     (typeof(AsyncCallState))
				.stfld      (field)
				.ldfld      (field)
				.MarkLabel  (checkCookie)
				;
		}
		private void EmitMethodName(EmitHelper emit)
		{
			object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(ActionNameAttribute), true);

			string methodName = attrs == null || attrs.Length == 0?
				Context.CurrentMethod.Name: ((ActionNameAttribute)attrs[0]).Name;

			emit
				.ldarg_0
				.ldstr     (methodName)
				;
		}
		private void EmitAsyncCall(List<ParameterInfo> parameters, EmitHelper emit, ParameterInfo callback, ParameterInfo exceptionCallback)
		{
			if (Context.CurrentMethod.IsDefined(typeof(UpToDateAttribute), true))
			{
				EmitCookie(emit);
			}
			else
			{
				emit.ldnull.end();
			}

			if (exceptionCallback != null)
			{
				emit.ldarg(exceptionCallback);
			}
			else
			{
				emit.ldnull.end();
			}

			emit.ldarg(callback);

			EmitParameters(emit, parameters);

			emit
				.call(typeof(WebClientBase), "InvokeAsync", typeof(string), typeof(AsyncCallState), typeof(Action<Exception>), typeof(Delegate), typeof(object[]))
				;
		}
		public void Emit(FieldInfo field, ref EmitHelper serializerEmit, ref EmitHelper deserializeEmit)
		{
			EmitSerialize(field, ref serializerEmit);
			EmitDeserialize(field, ref deserializeEmit);
		}
		public void Emit(PropertyInfo property, ref EmitHelper serializerEmit, ref EmitHelper deserializeEmit)
		{
			EmitSerialize(property, ref serializerEmit);			
			EmitDeserialize(property, ref deserializeEmit);
		}
Beispiel #14
0
		private LocalBuilder GetInitContextBuilder(
			string initContextName, EmitHelper emit)
		{
			LocalBuilder initField = (LocalBuilder)Context.Items[initContextName];

			if (initField == null)
			{
				Context.Items[initContextName] = initField = emit.DeclareLocal(InitContextType);

				emit
					.newobj   (InitContextType.GetPublicDefaultConstructor())

					.dup
					.ldarg_0
					.callvirt (InitContextType.GetProperty("Parent").GetSetMethod())

					.dup
					.ldc_i4_1
					.callvirt (InitContextType.GetProperty("IsInternal").GetSetMethod())

					.stloc    (initField)
					;

				Context.Items.Add("$BLToolkit.Default.DirtyParameters", false);
			}

			return initField;
		}
		private bool EmitParameters(EmitHelper emit, List<ParameterInfo> parameters)
		{
			bool hasOutRefParameters = false;

			int count = parameters.Count;
			for (int i = 0; i < count; i++)
			{
				if (parameters[i].IsOut)
				{
					count--;
					hasOutRefParameters = true;
				}
			}

			emit
				.ldc_i4_(count)
				.newarr(typeof(object))
				;

			int idx = 0;
			for (int i = 0; i < parameters.Count; i++)
			{
				ParameterInfo pi = parameters[i];

				if (pi.IsOut)
				{
					// Output-only parameter
					//
					continue;
				}

				if (pi.ParameterType.IsByRef)
					hasOutRefParameters = true;

				emit
					.dup
					.ldc_i4_    (idx)
					.ldargEx    (pi, true)
					.stelem_ref
					.end()
					;

				++idx;
			}

			return hasOutRefParameters;
		}
Beispiel #16
0
		private void CreateInitContextLazyInstance(
			FieldBuilder field,
			TypeHelper   fieldType,
			TypeHelper   objectType,
			EmitHelper   emit,
			object[]     parameters)
		{
			if (!CheckObjectHolderCtor(fieldType, objectType))
				return;

			LocalBuilder initField = emit.DeclareLocal(InitContextType);

			emit
				.newobj   (InitContextType.GetPublicDefaultConstructor())

				.dup
				.ldarg_0
				.callvirt (InitContextType.GetProperty("Parent").GetSetMethod())

				.dup
				.ldc_i4_1
				.callvirt (InitContextType.GetProperty("IsInternal").GetSetMethod())

				.dup
				.ldc_i4_1
				.callvirt (InitContextType.GetProperty("IsLazyInstance").GetSetMethod())

				;

			if (parameters != null)
			{
				emit
					.dup
					.ldsfld   (GetParameterField())
					.callvirt (InitContextType.GetProperty("MemberParameters").GetSetMethod())
					;
			}

			emit
				.stloc    (initField);

			if (objectType.IsAbstract)
			{
				emit
					.ldarg_0
					.ldsfld             (GetTypeAccessorField())
					.ldloc              (initField)
					.callvirtNoGenerics (typeof(TypeAccessor), "CreateInstanceEx", _initContextType)
					.isinst             (objectType)
					;
			}
			else
			{
				emit
					.ldarg_0
					.ldloc   (initField)
					.newobj  (objectType.GetPublicConstructor(typeof(InitContext)))
					;
			}

			if (IsObjectHolder)
			{
				emit
					.newobj (fieldType, objectType)
					;
			}

			emit
				.stfld (field)
				;
		}
		private void EmitSyncCall(List<ParameterInfo> parameters, EmitHelper emit)
		{
			Context.MethodBuilder.MethodBuilder.SetCustomAttribute(_soapDocumentAttributeBuilder);

			bool withOutParameters = EmitParameters(emit, parameters);
			bool callGeneric = !withOutParameters && Context.CurrentMethod.ReturnType != typeof(void);

			// Use Invoke<T>() for methods with return value but
			// Invoke() for methods with no return value or with out/ref parameters.
			//
			MethodInfo invoke = TypeHelper.GetMethod(
				typeof(WebClientBase),
				callGeneric,
				"Invoke",
				BindingFlags.Public | BindingFlags.Instance);

			if (callGeneric)
			{
				emit
					.call   (invoke.MakeGenericMethod(Context.CurrentMethod.ReturnType))
					.stloc  (Context.ReturnValue)
					;
			}
			else
			{
				if (withOutParameters)
				{
					LocalBuilder ret = emit.DeclareLocal(typeof(object[]));
					Label       exit = emit.DefineLabel();

					emit
						.call       (invoke)
						.dup
						.stloc      (ret)
						.brfalse_s  (exit)
						;

					int idx = 0;

					if (Context.CurrentMethod.ReturnType != typeof(void))
					{
						emit
							.ldloc          (ret)
							.ldc_i4_0
							.ldelem_ref
							.CastFromObject (Context.CurrentMethod.ReturnType)
							.stloc          (Context.ReturnValue)
							;

						++idx;
					}

					for (int i = 0; i < parameters.Count; ++i)
					{
						ParameterInfo pi = parameters[i];
						Type        type = pi.ParameterType;

						if (!type.IsByRef)
							continue;

						// Get ride of ref
						//
						type = type.GetElementType();

						emit
							.ldarg          (pi)
							.ldloc          (ret)
							.ldc_i4_        (idx)
							.ldelem_ref
							.CastFromObject (type)
							.stind          (type)
							;

						++idx;
					}

					emit.MarkLabel(exit);
				}
				else
				{
					emit
						.call  (invoke)
						.pop
						.end   ()
						;
				}
			}
		}
		public void Emit(FieldInfo field, ref EmitHelper serializerEmit, ref EmitHelper deserializeEmit)
		{
			var writeIntMethod = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) });
			var writeStringMethod = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(string) });
			var arrayNotNullLabel = serializerEmit.DefineLabel();
			var arrayNullLabel = serializerEmit.DefineLabel();
			var whileLabel = serializerEmit.DefineLabel();
			var endWhileLabel = serializerEmit.DefineLabel();
			var elementType = field.FieldType.GetElementType();
			var iLocal = serializerEmit.DeclareLocal(typeof(int));
			var lenLocal = serializerEmit.DeclareLocal(typeof(int));
			serializerEmit
				.ldarg_0
				.ldfld(field)
				.brtrue(arrayNotNullLabel)
				.ldarg_1
				.ldc_i4_m1
				.call(writeIntMethod)
				.br(arrayNullLabel);
			serializerEmit
				.MarkLabel(arrayNotNullLabel)
				.ldc_i4_0
				.stloc(iLocal)
				.ldarg_0
				.ldfld(field)
				.ldlen
				.conv_i4
				.stloc(lenLocal)
				.ldarg_1
				.ldloc(lenLocal)
				.call(writeIntMethod)
				.br(endWhileLabel)
				.MarkLabel(whileLabel);
			#region string
			if (elementType == typeof(string))
			{
				var strElement = serializerEmit.DeclareLocal(typeof(string));
				var strElementNullLbl = serializerEmit.DefineLabel();
				var strElementNotNullLbl = serializerEmit.DefineLabel();
				serializerEmit
					.ldarg_0
					.ldfld(field)
					.ldloc(iLocal)
					.ldelem_ref
					.stloc(strElement)
					.ldloc(strElement)
					.brtrue(strElementNotNullLbl)
					.ldarg_1
					.ldc_i4_m1
					.call(writeIntMethod)
					.br(strElementNullLbl)
					.MarkLabel(strElementNotNullLbl)
					.ldarg_1
					.ldloc(strElement)
					.call(typeof(string).GetMethod("get_Length"))
					.call(writeIntMethod)
					.ldarg_1
					.ldloc(strElement)
					.call(writeStringMethod)
					.MarkLabel(strElementNullLbl)
					.ldloc(iLocal)
					.ldc_i4_1
					.add
					.stloc(iLocal);
			}
			#endregion

			#region Primitive, DateTime, decimal
			else if (elementType.IsPrimitive || elementType == typeof(DateTime) || elementType == typeof(decimal))
			{
				serializerEmit
					.ldarg_1
					.ldarg_0
					.ldfld(field)
					.ldloc(iLocal)
					.dup
					.ldc_i4_1
					.add
					.stloc(iLocal);
				if (elementType == typeof(bool) || elementType == typeof(sbyte))
				{
					serializerEmit = serializerEmit.ldelem_i1;
				}
				else if (elementType == typeof(byte))
				{
					serializerEmit = serializerEmit.ldelem_u1;
				}
				else if (elementType == typeof(char) || elementType == typeof(ushort))
				{
					serializerEmit = serializerEmit.ldelem_u2;
				}
				else if (elementType == typeof(short))
				{
					serializerEmit = serializerEmit.ldelem_i2;
				}
				else if (elementType == typeof(int))
				{
					serializerEmit = serializerEmit.ldelem_i4;
				}
				else if (elementType == typeof(uint))
				{
					serializerEmit = serializerEmit.ldelem_u4;
				}
				else if (elementType == typeof(float))
				{
					serializerEmit = serializerEmit.ldelem_r4;
				}
				else if (elementType == typeof(long) || elementType == typeof(ulong))
				{
					serializerEmit = serializerEmit.ldelem_i8;
				}
				else if (elementType == typeof(double))
				{
					serializerEmit = serializerEmit.ldelem_r8;
				}
				else if (elementType == typeof(decimal))
				{
					serializerEmit = serializerEmit.ldelema(elementType).ldobj(elementType);
				}
				else if (elementType == typeof(DateTime))
				{
					serializerEmit = serializerEmit.ldelema(elementType).call(typeof(DateTime).GetMethod("get_Ticks"));
				}
				var writeElementType = elementType != typeof(DateTime) ? elementType : typeof(long);
				serializerEmit
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { writeElementType }));
			}
			#endregion

			#region object
			else if (elementType.IsClass)
			{
				var obj = serializerEmit.DeclareLocal(typeof(object));
				var elementNullLabel = serializerEmit.DefineLabel();
				var elementNotNullLabel = serializerEmit.DefineLabel();
				var objectExistsLocal = serializerEmit.DefineLabel();
				var objectNotExistsLocal = serializerEmit.DefineLabel();
				serializerEmit
					.ldarg_0
					.ldfld(field)
					.ldloc(iLocal)
					.ldelem_ref
					.stloc(obj)
					.ldloc(obj)
					.brtrue(elementNotNullLabel)
					.ldarg_1
					.ldc_i4_m1
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.br(elementNullLabel)
					.MarkLabel(elementNotNullLabel)
					.ldarg_2
					.ldloc(obj)
					.call(typeof(IDictionary<object, int>).GetMethod("ContainsKey", new[] { typeof(object) }))
					.brtrue(objectExistsLocal)
					.ldarg_1
					.ldarg_3
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.ldloc(obj)
					.castclass(typeof(ISerializable))
					.ldarg_1
					.ldarg_2
					.ldarg_3
					.call(typeof(ISerializable).GetMethod("Serialize"))
					.br(objectNotExistsLocal)
					.MarkLabel(objectExistsLocal)
					.ldarg_1
					.ldarg_2
					.ldloc(obj)
					.call(typeof(IDictionary<object, int>).GetMethod("get_Item", new[] { typeof(object) }))
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.MarkLabel(objectNotExistsLocal)
					.MarkLabel(elementNullLabel)
					.ldloc(iLocal)
					.ldc_i4_1
					.add
					.stloc(iLocal);
			}
			#endregion

			serializerEmit
				.MarkLabel(endWhileLabel)
				.ldloc(iLocal)
				.ldloc(lenLocal)
				.blt(whileLabel)
				.MarkLabel(arrayNullLabel);

			var readIntMethod = typeof(BinaryReader).GetMethod("ReadInt32");
			var arrayNotNullLabel2 = deserializeEmit.DefineLabel();
			var arrayNullLabel2 = deserializeEmit.DefineLabel();
			var arrayLocal = deserializeEmit.DeclareLocal(field.FieldType);
			var len = deserializeEmit.DeclareLocal(typeof(int));
			var i = deserializeEmit.DeclareLocal(typeof(int));
			var beginForLabel = deserializeEmit.DefineLabel();
			var beginForBodyLabel = deserializeEmit.DefineLabel();
			deserializeEmit = deserializeEmit
				.ldarg_1
				.call(readIntMethod)
				.stloc(len)
				.ldloc(len)
				.ldc_i4_m1
				.ceq
				.brfalse(arrayNotNullLabel2)
				.ldarg_0
				.ldnull
				.stfld(field)
				.br(arrayNullLabel2)
				.MarkLabel(arrayNotNullLabel2)
				.ldloc(len)
				.newarr(elementType)
				.stloc(arrayLocal)
				.ldc_i4_0
				.stloc(i)
				.br(beginForLabel)
				.MarkLabel(beginForBodyLabel);
			#region Primitive, decimal, DateTime
			if (elementType.IsPrimitive)
			{
				deserializeEmit
					.ldloc(arrayLocal)
					.ldloc(i)
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("Read" + elementType.Name));
				if (elementType == typeof(bool) || elementType == typeof(sbyte) || elementType == typeof(byte))
				{
					deserializeEmit = deserializeEmit.stelem_i1;
				}
				else if (elementType == typeof(char) || elementType == typeof(ushort) || elementType == typeof(short))
				{
					deserializeEmit = deserializeEmit.stelem_i2;
				}
				else if (elementType == typeof(int) || elementType == typeof(uint))
				{
					deserializeEmit = deserializeEmit.stelem_i4;
				}
				else if (elementType == typeof(float))
				{
					deserializeEmit = deserializeEmit.stelem_r4;
				}
				else if (elementType == typeof(long) || elementType == typeof(ulong))
				{
					deserializeEmit = deserializeEmit.stelem_i8;
				}
				else if (elementType == typeof(double))
				{
					deserializeEmit = deserializeEmit.stelem_r8;
				}
			}
			else if (elementType == typeof(decimal))
			{
				deserializeEmit
					.ldloc(arrayLocal)
					.ldloc(i)
					.ldelema(typeof(decimal))
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadDecimal"))
					.stobj(typeof(decimal));
			}
			else if (elementType == typeof(DateTime))
			{
				deserializeEmit
					.ldloc(arrayLocal)
					.ldloc(i)
					.ldelema(typeof(DateTime))
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadInt64"))
					.newobj(typeof(DateTime), typeof(long))
					.stobj(typeof(DateTime));
			}
			#endregion

			#region string
			else if (elementType == typeof(string))
			{
				var strLen = deserializeEmit.DeclareLocal(typeof(int));
				var strNullLabel = deserializeEmit.DefineLabel();
				var strNotNullLabel = deserializeEmit.DefineLabel();
				deserializeEmit
					.ldarg_1
					.call(readIntMethod)
					.stloc(strLen)
					.ldloc(strLen)
					.ldc_i4_m1
					.ceq
					.brfalse(strNotNullLabel)
					.ldloc(arrayLocal)
					.ldloc(i)
					.ldelema(typeof(string))
					.ldnull
					.stobj(typeof(string))
					.br(strNullLabel)
					.MarkLabel(strNotNullLabel)
					.ldloc(arrayLocal)
					.ldloc(i)
					.ldelema(typeof(string))
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadString"))
					.stobj(typeof(string))
					.MarkLabel(strNullLabel);
			}
			#endregion

			#region object
			var desElementNullLabel = deserializeEmit.DefineLabel();
			var desElementNotNullLabel = deserializeEmit.DefineLabel();
			var propertyInstanceType = deserializeEmit.DeclareLocal(typeof(Type));
			var indexLocal = deserializeEmit.DeclareLocal(typeof(int));
			var desobjectExistsLocal = deserializeEmit.DefineLabel();
			var desobjectNotExistsLocal = deserializeEmit.DefineLabel();
			deserializeEmit
				.ldarg_1
				.call(typeof(BinaryReader).GetMethod("ReadInt32"))
				.stloc(indexLocal)
				.ldloc(indexLocal)
				.ldc_i4_m1
				.ceq
				.brfalse(desElementNotNullLabel)
				.ldloc(arrayLocal)
				.ldloc(i)
				.ldelema(elementType)
				.ldnull
				.stobj(elementType)
				.br(desElementNullLabel)
				.MarkLabel(desElementNotNullLabel)
				.ldarg_2
				.ldloc(indexLocal)
				.call(typeof(IDictionary<int, object>).GetMethod("ContainsKey", new Type[] { typeof(int) }))
				.brfalse(desobjectNotExistsLocal)
				.ldloc(arrayLocal)
				.ldloc(i)
				.ldelema(elementType)
				.ldarg_2
				.ldloc(indexLocal)
				.call(typeof(IDictionary<int, object>).GetMethod("get_Item", new Type[] { typeof(int) }))
				.castclass(elementType)
				.stobj(elementType)
				.br(desobjectExistsLocal)
				.MarkLabel(desobjectNotExistsLocal)
				.ldarg_1
				.call(typeof(BinaryReader).GetMethod("ReadString"))
				.call(typeof(Type).GetMethod("GetType", new Type[] { typeof(string) }))
				.stloc(propertyInstanceType)
				.ldloc(arrayLocal)
				.ldloc(i)
				.ldelema(elementType)
				.ldloc(propertyInstanceType)
				.call(typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type) }))
				.castclass(elementType)
				.stobj(elementType)
				.ldarg_2
				.ldloc(indexLocal)
				.ldloc(arrayLocal)
				.ldloc(i)
				.ldelem_ref
				.call(typeof(IDictionary<int, object>).GetMethod("Add", new[] { typeof(int), typeof(object) }))
				.ldloc(arrayLocal)
				.ldloc(i)
				.ldelem_ref
				.castclass(typeof(ISerializable))
				.ldarg_1
				.ldarg_2
				.call(typeof(ISerializable).GetMethod("Deserialize", new Type[] { typeof(BinaryReader), typeof(IDictionary<int, object>) }))
				.MarkLabel(desobjectExistsLocal)
				.MarkLabel(desElementNullLabel);
			#endregion

			deserializeEmit
				.ldloc(i)
				.ldc_i4_1
				.add
				.stloc(i)
				.MarkLabel(beginForLabel)
				.ldloc(i)
				.ldloc(len)
				.clt
				.brtrue(beginForBodyLabel)
				.ldarg_0
				.ldloc(arrayLocal)
				.stfld(field)
				.MarkLabel(arrayNullLabel2);
		}
Beispiel #19
0
		private void BuildHolderInstance(EmitHelper emit)
		{
			string       fieldName  = GetFieldName();
			FieldBuilder field      = Context.GetField(fieldName);
			TypeHelper   fieldType  = new TypeHelper(field.FieldType);
			TypeHelper   objectType = new TypeHelper(GetObjectType());

			ConstructorInfo ci = fieldType.GetPublicDefaultConstructor();

			if (ci != null)
			{
				emit
					.ldarg_0
					.newobj (ci)
					.stfld  (field)
					;
			}
			else
			{
				if (!CheckObjectHolderCtor(fieldType, objectType))
					return;

				emit
					.ldarg_0
					.ldnull
					.newobj (fieldType, objectType)
					.stfld  (field)
					;
			}
		}
Beispiel #20
0
		private void CheckNull(EmitHelper emit)
		{
			if (_throwExceptionIfNull == false && string.IsNullOrEmpty(_exceptionMessage))
			{
				emit
					.brfalse (Context.ReturnLabel)
					;
			}
			else
			{
				string message = string.Format(
					string.IsNullOrEmpty(_exceptionMessage)?
						"'{0}.{1}' is not initialized." : _exceptionMessage,
					_targetInterface.Name, _memberName, _targetInterface.FullName);

				Label label = emit.DefineLabel();

				emit
					.brtrue    (label)
					.ldstr     (message)
					.newobj    (typeof(InvalidOperationException), typeof(string))
					.@throw
					.MarkLabel (label)
					;
			}
		}
		public void Emit(FieldInfo field, ref EmitHelper serializerEmit, ref EmitHelper deserializeEmit)
		{
			var fieldType = field.FieldType;
			var writerMethod = typeof(BinaryWriter).GetMethod("Write", new Type[] { fieldType });
			var readerMethod = typeof(BinaryReader).GetMethod("Read" + fieldType.Name);
			if (fieldType.IsPrimitive || fieldType == typeof(decimal))
			{
				serializerEmit
					.ldarg_1
					.ldarg_0
					.ldfld(field)
					.call(writerMethod);
				deserializeEmit
					.ldarg_0
					.ldarg_1
					.call(readerMethod)
					.stfld(field);
			}
			else if (fieldType == typeof(DateTime))
			{
				var writeLongMethod = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(long) });
				var readLongMethod = typeof(BinaryReader).GetMethod("ReadInt64");
				serializerEmit.DeclareLocal(typeof(DateTime));
				serializerEmit
					.ldarg_1
					.ldarg_0
					.ldfld(field)
					.stloc_0
					.ldloca(0)
					.call(typeof(DateTime).GetMethod("get_Ticks"))
					.call(writeLongMethod);
				deserializeEmit
					.ldarg_0
					.ldarg_1
					.call(readLongMethod)
					.newobj(typeof(DateTime), new[] { typeof(long) })
					.stfld(field);
			}
			else if (fieldType == typeof(string))
			{
				var stringLocal = serializerEmit.DeclareLocal(fieldType);
				var stringNullLabel = serializerEmit.DefineLabel();
				var stringNotNullLabel = serializerEmit.DefineLabel();
				serializerEmit
					.ldarg_0
					.ldfld(field)
					.stloc(stringLocal)
					.ldloc(stringLocal)
					.brtrue(stringNotNullLabel)
					.ldarg_1
					.ldc_i4_m1
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.br(stringNullLabel)
					.MarkLabel(stringNotNullLabel)
					.ldarg_1
					.ldloc(stringLocal)
					.call(typeof(string).GetMethod("get_Length"))
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }))
					.ldarg_1
					.ldloc(stringLocal)
					.call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(string) }))
					.MarkLabel(stringNullLabel);
				var valueNotNullLabel = deserializeEmit.DefineLabel();
				var valueNullLabel = deserializeEmit.DefineLabel();
				deserializeEmit
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadInt32"))
					.ldc_i4_m1
					.ceq
					.brfalse(valueNotNullLabel)
					.ldarg_0
					.ldnull
					.stfld(field)
					.br(valueNullLabel)
					.MarkLabel(valueNotNullLabel)
					.ldarg_0
					.ldarg_1
					.call(typeof(BinaryReader).GetMethod("ReadString"))
					.stfld(field)
					.MarkLabel(valueNullLabel);
			}
		}