protected internal override Delegate CreateDelegate() { MemberInfo member = CallInfo.MemberInfo; if (member == null) { member = LookupUtils.GetMember(CallInfo); CallInfo.IsStatic = member.IsStatic(); } bool handleInnerStruct = CallInfo.ShouldHandleInnerStruct; if (handleInnerStruct) { Generator.ldarg_0 // load arg-0 (this) .DeclareLocal(CallInfo.TargetType); // TargetType tmpStr LoadInnerStructToLocal(0); // tmpStr = ((ValueTypeHolder)this)).Value Generator.DeclareLocal(Constants.ObjectType); // object result; } else if (!CallInfo.IsStatic) { Generator.ldarg_0 // load arg-0 (this) .castclass(CallInfo.TargetType); // (TargetType)this } if (member.MemberType == MemberTypes.Field) { var field = member as FieldInfo; if (field.DeclaringType.IsEnum) // special enum handling as ldsfld does not support enums { Generator.ldc_i4((int)field.GetValue(field.DeclaringType)) .boxIfValueType(field.FieldType); } else { Generator.ldfld(field.IsStatic, field) // (this|tmpStr).field OR TargetType.field .boxIfValueType(field.FieldType); // (object)<stack> } } else { var prop = member as PropertyInfo; MethodInfo getMethod = LookupUtils.GetPropertyGetMethod(prop, CallInfo); Generator.call(getMethod.IsStatic || CallInfo.IsTargetTypeStruct, getMethod) // (this|tmpStr).prop OR TargetType.prop .boxIfValueType(prop.PropertyType); // (object)<stack> } if (handleInnerStruct) { Generator.stloc_1.end(); // resultLocal = <stack> StoreLocalToInnerStruct(0); // ((ValueTypeHolder)this)).Value = tmpStr Generator.ldloc_1.end(); // push resultLocal } Generator.ret(); return(Method.CreateDelegate(typeof(MemberGetter))); }
protected internal override Delegate CreateDelegate() { MemberInfo member = CallInfo.MemberInfo; if (member == null) { member = LookupUtils.GetMember(CallInfo); CallInfo.IsStatic = member.IsStatic(); } bool handleInnerStruct = CallInfo.ShouldHandleInnerStruct; if (CallInfo.IsStatic) { Generator.ldarg_1.end(); // load value-to-be-set } else { Generator.ldarg_0.end(); // load arg-0 (this) if (handleInnerStruct) { Generator.DeclareLocal(CallInfo.TargetType); // TargetType tmpStr LoadInnerStructToLocal(0); // tmpStr = ((ValueTypeHolder)this)).Value; Generator.ldarg_1.end(); // load value-to-be-set; } else { Generator.castclass(CallInfo.TargetType) // (TargetType)this .ldarg_1.end(); // load value-to-be-set; } } Generator.CastFromObject(member.Type()); // unbox | cast value-to-be-set if (member.MemberType == MemberTypes.Field) { var field = member as FieldInfo; Generator.stfld(field.IsStatic, field); // (this|tmpStr).field = value-to-be-set; } else { var prop = member as PropertyInfo; MethodInfo setMethod = LookupUtils.GetPropertySetMethod(prop, CallInfo); Generator.call(setMethod.IsStatic || CallInfo.IsTargetTypeStruct, setMethod); // (this|tmpStr).set_Prop(value-to-be-set); } if (handleInnerStruct) { StoreLocalToInnerStruct(0); // ((ValueTypeHolder)this)).Value = tmpStr } Generator.ret(); return(Method.CreateDelegate(typeof(MemberSetter))); }
protected internal override Delegate CreateDelegate() { var method = (MethodInfo)CallInfo.MemberInfo ?? LookupUtils.GetMethod(CallInfo); CallInfo.IsStatic = method.IsStatic; const byte paramArrayIndex = 1; bool hasReturnType = method.ReturnType != Constants.VoidType; byte startUsableLocalIndex = 0; if (CallInfo.HasRefParam) { startUsableLocalIndex = CreateLocalsForByRefParams(paramArrayIndex, method); // create by_ref_locals from argument array Generator.DeclareLocal(hasReturnType ? method.ReturnType : Constants.ObjectType); // T result; GenerateInvocation(method, paramArrayIndex, (byte)(startUsableLocalIndex + 1)); if (hasReturnType) { Generator.stloc(startUsableLocalIndex); // result = <stack>; } AssignByRefParamsToArray(paramArrayIndex); // store by_ref_locals back to argument array } else { Generator.DeclareLocal(hasReturnType ? method.ReturnType : Constants.ObjectType); // T result; GenerateInvocation(method, paramArrayIndex, (byte)(startUsableLocalIndex + 1)); if (hasReturnType) { Generator.stloc(startUsableLocalIndex); // result = <stack>; } } if (CallInfo.ShouldHandleInnerStruct) { StoreLocalToInnerStruct((byte)(startUsableLocalIndex + 1)); // ((ValueTypeHolder)this)).Value = tmpStr; } if (hasReturnType) { Generator.ldloc(startUsableLocalIndex) // push result; .boxIfValueType(method.ReturnType); // box result; } else { Generator.ldnull.end(); // load null } Generator.ret(); return(Method.CreateDelegate(typeof(MethodInvoker))); }
protected internal override Delegate CreateDelegate() { if (CallInfo.IsTargetTypeStruct && CallInfo.HasNoParam) // no-arg struct needs special initialization { Generator.DeclareLocal(CallInfo.TargetType); // TargetType tmp Generator.ldloca_s(0) // &tmp .initobj(CallInfo.TargetType) // init_obj(&tmp) .ldloc_0.end(); // load tmp } else if (CallInfo.TargetType.IsArray) { Generator.ldarg_0 // load args[] (method arguments) .ldc_i4_0 // load 0 .ldelem_ref // load args[0] (length) .unbox_any(typeof(int)) // unbox stack .newarr(CallInfo.TargetType.GetElementType()); // new T[args[0]] } else { ConstructorInfo ctorInfo = LookupUtils.GetConstructor(CallInfo); byte startUsableLocalIndex = 0; if (CallInfo.HasRefParam) { startUsableLocalIndex = CreateLocalsForByRefParams(0, ctorInfo); // create by_ref_locals from argument array Generator.DeclareLocal(CallInfo.TargetType); // TargetType tmp; } PushParamsOrLocalsToStack(0); // push arguments and by_ref_locals Generator.newobj(ctorInfo); // ctor (<stack>) if (CallInfo.HasRefParam) { Generator.stloc(startUsableLocalIndex); // tmp = <stack>; AssignByRefParamsToArray(0); // store by_ref_locals back to argument array Generator.ldloc(startUsableLocalIndex); // tmp } } Generator.boxIfValueType(CallInfo.TargetType) .ret(); // return (box)<stack>; return(Method.CreateDelegate(typeof(ConstructorInvoker))); }