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); }
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 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 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[])) ; }