protected byte CreateLocalsForByRefParams(byte paramArrayIndex, MethodBase invocationInfo) { byte numberOfByRefParams = 0; ParameterInfo[] parameters = invocationInfo.GetParameters(); for (int i = 0, count = ParamTypes.Length; i < count; ++i) { Type paramType = ParamTypes[i]; if (paramType.IsByRef) { Type type = paramType.GetElementType(); Gen.DeclareLocal(type); if (!parameters[i].IsOut) // no initialization necessary is 'out' parameter { Gen.Emit(OpCodes.Ldarg, (short)paramArrayIndex); Gen.Emit(OpCodes.Ldc_I4, i); Gen.Emit(OpCodes.Ldelem_Ref); if (type == typeof(object)) { Gen.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type); } stloc_s(numberOfByRefParams); } numberOfByRefParams++; } } return(numberOfByRefParams); }
protected internal override Delegate CreateDelegate() { bool handleInnerStruct = ShouldHandleInnerStruct; if (handleInnerStruct) { Gen.Emit(OpCodes.Ldarg_0); // load arg-0 (this) Gen.DeclareLocal(TargetType); // TargetType tmpStr LoadInnerStructToLocal(0); // tmpStr = ((ValueTypeHolder)this)).Value Gen.DeclareLocal(typeof(object)); // object result; } else if (!IsStatic) { Gen.Emit(OpCodes.Ldarg_0); // load arg-0 (this) Gen.Emit(OpCodes.Castclass, TargetType); // (TargetType)this } if (MemberInfo is FieldInfo field) { if (field.DeclaringType.IsEnum) // special enum handling as ldsfld does not support enums { Gen.Emit(OpCodes.Ldc_I4, (int)field.GetValue(field.DeclaringType)); } else { Gen.Emit(field.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, field); // (this|tmpStr).field OR TargetType.field } if (field.FieldType.IsValueType) { Gen.Emit(OpCodes.Box, field.FieldType); // (object)<stack> } } else { PropertyInfo prop = (PropertyInfo)MemberInfo; MethodInfo getMethod = prop.GetGetMethod(true); Gen.Emit(getMethod.IsStatic || IsTargetTypeStruct ? OpCodes.Call : OpCodes.Callvirt, getMethod); // (this|tmpStr).prop OR TargetType.prop if (prop.PropertyType.IsValueType) { Gen.Emit(OpCodes.Box, prop.PropertyType); // (object)<stack> } } if (handleInnerStruct) { Gen.Emit(OpCodes.Stloc_1); // resultLocal = <stack> StoreLocalToInnerStruct(0); // ((ValueTypeHolder)this)).Value = tmpStr Gen.Emit(OpCodes.Ldloc_1); // push resultLocal } Gen.Emit(OpCodes.Ret); return(Method.CreateDelegate(typeof(MemberGetter))); }
protected internal override Delegate CreateDelegate() { MethodInfo method = (MethodInfo)MemberInfo; const byte paramArrayIndex = 1; bool hasReturnType = method.ReturnType != typeof(void); byte startUsableLocalIndex = 0; if (HasRefParam) { startUsableLocalIndex = CreateLocalsForByRefParams(paramArrayIndex, method); // create by_ref_locals from argument array Gen.DeclareLocal(hasReturnType ? method.ReturnType : typeof(object)); // T result; GenerateInvocation(method, paramArrayIndex, (byte)(startUsableLocalIndex + 1)); if (hasReturnType) { stloc_s(startUsableLocalIndex); // result = <stack>; } AssignByRefParamsToArray(paramArrayIndex); // store by_ref_locals back to argument array } else { Gen.DeclareLocal(hasReturnType ? method.ReturnType : typeof(object)); // T result; GenerateInvocation(method, paramArrayIndex, (byte)(startUsableLocalIndex + 1)); if (hasReturnType) { stloc_s(startUsableLocalIndex); // result = <stack>; } } if (ShouldHandleInnerStruct) { StoreLocalToInnerStruct((short)(startUsableLocalIndex + 1)); // ((ValueTypeHolder)this)).Value = tmpStr; } if (hasReturnType) { Gen.Emit(OpCodes.Ldloc, (short)startUsableLocalIndex); // push result; if (method.ReturnType.IsValueType) { Gen.Emit(OpCodes.Box, method.ReturnType); // box result; } } else { Gen.Emit(OpCodes.Ldnull); // load null } Gen.Emit(OpCodes.Ret); return(Method.CreateDelegate(typeof(MethodInvoker))); }
protected void GenerateInvocation(MethodInfo methodInfo, byte paramArrayIndex, byte structLocalPosition) { if (!IsStatic) { Gen.Emit(OpCodes.Ldarg_0); // load arg-0 (this/null); if (ShouldHandleInnerStruct) { Gen.DeclareLocal(TargetType); // TargetType tmpStr; LoadInnerStructToLocal(structLocalPosition); // tmpStr = ((ValueTypeHolder)this)).Value; } else { Gen.Emit(OpCodes.Castclass, TargetType); // (TargetType)arg-0; } } PushParamsOrLocalsToStack(paramArrayIndex); // push arguments and by_ref_locals Gen.Emit(methodInfo.IsStatic || IsTargetTypeStruct ? OpCodes.Call : OpCodes.Callvirt, methodInfo); // call OR callvirt }
protected internal override Delegate CreateDelegate() { bool handleInnerStruct = ShouldHandleInnerStruct; if (!IsStatic) { Gen.Emit(OpCodes.Ldarg_0); // load arg-0 (this) if (handleInnerStruct) { Gen.DeclareLocal(TargetType); // TargetType tmpStr LoadInnerStructToLocal(0); // tmpStr = ((ValueTypeHolder)this)).Value; } else { Gen.Emit(OpCodes.Castclass, TargetType); // (TargetType)this } } Gen.Emit(OpCodes.Ldarg_1); // load value-to-be-set; Type type = MemberInfo.Type(); if (type != typeof(object)) { Gen.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type); } if (MemberInfo is FieldInfo field) { Gen.Emit(field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, field); // (this|tmpStr).field = value-to-be-set; } else { PropertyInfo prop = (PropertyInfo)MemberInfo; MethodInfo setMethod = prop.GetSetMethod(true); Gen.Emit(setMethod.IsStatic || IsTargetTypeStruct ? OpCodes.Call : OpCodes.Callvirt, setMethod); // (this|tmpStr).set_Prop(value-to-be-set); } if (handleInnerStruct) { StoreLocalToInnerStruct(0); // ((ValueTypeHolder)this)).Value = tmpStr } Gen.Emit(OpCodes.Ret); return(Method.CreateDelegate(typeof(MemberSetter))); }
protected internal override Delegate CreateDelegate() { if (IsTargetTypeStruct && HasNoParam) // no-arg struct needs special initialization { Gen.DeclareLocal(TargetType); // TargetType tmp Gen.Emit(OpCodes.Ldloca_S, (byte)0); // &tmp Gen.Emit(OpCodes.Initobj, TargetType); // init_obj(&tmp) Gen.Emit(OpCodes.Ldloc_0); // load tmp } else if (TargetType.IsArray) { Gen.Emit(OpCodes.Ldarg_0); // load args[] (method arguments) Gen.Emit(OpCodes.Ldc_I4_0); // load 0 Gen.Emit(OpCodes.Ldelem_Ref); // load args[0] (length) Gen.Emit(OpCodes.Unbox_Any, typeof(int)); // unbox stack Gen.Emit(OpCodes.Newarr, TargetType.GetElementType()); // new T[args[0]] } else { ConstructorInfo ctorInfo = (ConstructorInfo)MemberInfo; byte startUsableLocalIndex = 0; if (HasRefParam) { startUsableLocalIndex = CreateLocalsForByRefParams(0, ctorInfo); // create by_ref_locals from argument array Gen.DeclareLocal(TargetType); // TargetType tmp; } PushParamsOrLocalsToStack(0); // push arguments and by_ref_locals Gen.Emit(OpCodes.Newobj, ctorInfo); // ctor (<stack>) if (HasRefParam) { stloc_s(startUsableLocalIndex); // tmp = <stack>; AssignByRefParamsToArray(0); // store by_ref_locals back to argument array Gen.Emit(OpCodes.Ldloc, (short)startUsableLocalIndex); // tmp } } if (TargetType.IsValueType) { Gen.Emit(OpCodes.Box, TargetType); } Gen.Emit(OpCodes.Ret); // return (box)<stack>; return(Method.CreateDelegate(typeof(ConstructorInvoker))); }
protected internal override Delegate CreateDelegate() { bool handleInnerStruct = ShouldHandleInnerStruct; if (handleInnerStruct) { Gen.Emit(OpCodes.Ldarg_1); // load arg-1 (target) Gen.DeclareLocal(TargetType); // TargetType localStr; Gen.Emit(OpCodes.Castclass, typeof(ValueTypeHolder)); // (ValueTypeHolder)wrappedStruct Gen.Emit(OpCodes.Callvirt, StructGetMethod); // <stack>.get_Value() Gen.Emit(OpCodes.Unbox_Any, TargetType); // unbox <stack> Gen.Emit(OpCodes.Stloc_0); // localStr = <stack> } for (int i = 0, count = Sources.Count; i < count; ++i) { if (handleInnerStruct) { Gen.Emit(OpCodes.Ldloca_S, (byte)0); // load &localStr } else { Gen.Emit(OpCodes.Ldarg_1); Gen.Emit(OpCodes.Castclass, TargetType); // ((TargetType)target) } Gen.Emit(OpCodes.Ldarg_0); Gen.Emit(OpCodes.Castclass, SourceType); GenerateGetMemberValue(Sources[i]); GenerateSetMemberValue(Targets[i]); } if (handleInnerStruct) { StoreLocalToInnerStruct(1, 0); // ((ValueTypeHolder)this)).Value = tmpStr } Gen.Emit(OpCodes.Ret); return(Method.CreateDelegate(typeof(ObjectMapper))); }
protected internal override Delegate CreateDelegate() { bool handleInnerStruct = ShouldHandleInnerStruct; if (!IsStatic) { Gen.Emit(OpCodes.Ldarg_0); // load arg-0 (this) if (handleInnerStruct) { Gen.DeclareLocal(TargetType); // TargetType tmpStr Gen.Emit(OpCodes.Castclass, typeof(ValueTypeHolder)); // (ValueTypeHolder)wrappedStruct Gen.Emit(OpCodes.Callvirt, StructGetMethod); // <stack>.get_Value() Gen.Emit(OpCodes.Unbox_Any, TargetType); // unbox <stack> Gen.Emit(OpCodes.Stloc_0); // localStr = <stack> } else { Gen.Emit(OpCodes.Castclass, TargetType); // (TargetType)this } } IList <MemberInfo> members = Members; for (int i = 0, count = members.Count; i < count; ++i) { MemberInfo method = members[i]; if (method == null) { continue; } if (method is FieldInfo field) { if (!field.IsStatic) { if (handleInnerStruct) { Gen.Emit(OpCodes.Ldloca_S, (byte)0); } else if (i != count - 1) { Gen.Emit(OpCodes.Dup); } } Gen.Emit(OpCodes.Ldarg_1); Gen.Emit(OpCodes.Ldc_I4, i); Gen.Emit(OpCodes.Ldelem_Ref); if (field.FieldType != typeof(object)) { Gen.Emit(field.FieldType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, field.FieldType); } Gen.Emit(field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, field); // (this|tmpStr).field = value-to-be-set } else { PropertyInfo property = (PropertyInfo)method; MethodInfo setMethod = property.GetSetMethod(true) ?? throw new MemberAccessException(TargetType.FullName + "." + property.Name); if (!setMethod.IsStatic) { if (handleInnerStruct) { Gen.Emit(OpCodes.Ldloca_S, (byte)0); } else if (i != count - 1) { Gen.Emit(OpCodes.Dup); } } Gen.Emit(OpCodes.Ldarg_1); Gen.Emit(OpCodes.Ldc_I4, i); Gen.Emit(OpCodes.Ldelem_Ref); if (property.PropertyType != typeof(object)) { Gen.Emit(property.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, property.PropertyType); } Gen.Emit(setMethod.IsStatic || IsTargetTypeStruct ? OpCodes.Call : OpCodes.Callvirt, setMethod); // (this|tmpStr).set_Prop(value-to-be-set) } } if (handleInnerStruct) { StoreLocalToInnerStruct(0); // ((ValueTypeHolder)this)).Value = tmpStr } //Gen.Emit(OpCodes.Ldnull); // load null Gen.Emit(OpCodes.Ret); return(Method.CreateDelegate(typeof(MultiSetter))); }