private static void ImplementSharedExecuter(MethodBuilderContext context, MethodInfo initMethod, MethodInfo execMethod) { FieldBuilder field = null; if (initMethod != null) { field = context.TypeBuilder.DefineField("__methodField_" + context.Method.Name + context.Method.GetHashCode().ToString(), initMethod.ReturnType, FieldAttributes.Private); // Load instance for initializer context.InitMethodGenerator.Emit(OpCodes.Ldarg_0); context.InitMethodGenerator.Emit(OpCodes.Ldarg_0); context.InitMethodGenerator.Emit(OpCodes.Ldsfld, context.MethodInfoField); context.InitMethodGenerator.EmitCall(OpCodes.Call, initMethod, null); // Call init method context.InitMethodGenerator.Emit(OpCodes.Stfld, field); // Store result in field } // Create object array to hold all parameters and load on stack var parametersArray = context.ExecMethodGenerator.EmitParametersArray(context.Method); // Call executer(layer, state, params) context.ExecMethodGenerator.Emit(OpCodes.Ldarg_0); // Load instance as first param to execute if (field != null) { context.ExecMethodGenerator.Emit(OpCodes.Ldarg_0); // Load instance for load field context.ExecMethodGenerator.Emit(OpCodes.Ldfld, field); // Load infos array } else { context.ExecMethodGenerator.Emit(OpCodes.Ldsfld, context.MethodInfoField); } context.ExecMethodGenerator.Emit(OpCodes.Ldloc, parametersArray); // Load params as third param for execute context.ExecMethodGenerator.EmitCall(OpCodes.Call, execMethod, null); // Call execute method // Handle return value if (context.Method.ReturnType == typeof(void)) { context.ExecMethodGenerator.Emit(OpCodes.Pop); } else if (context.Method.ReturnType.IsValueType) { context.ExecMethodGenerator.Emit(OpCodes.Unbox_Any, context.Method.ReturnType); } }
private static void ImplementTarget(MethodBuilderContext context, string targetMemberName, Func <MethodInfo, MethodInfo> targetMethodSelector) { // Find target method MethodInfo targetMethod = targetMethodSelector(context.Method); if (targetMethod == null) { throw new ArgumentException("Target method for interface method {0} not found.", context.Method.Name); } // If method is instance, we need to find target instance and load it on stack if (!targetMethod.IsStatic) { MemberInfo getTargetMember = context.BaseClass.GetMember(targetMemberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public).Single(); context.ExecMethodGenerator.Emit(OpCodes.Ldarg_0); if (getTargetMember.MemberType == MemberTypes.Field) { context.ExecMethodGenerator.Emit(OpCodes.Ldfld, (FieldInfo)getTargetMember); } else if (getTargetMember.MemberType == MemberTypes.Property) { context.ExecMethodGenerator.EmitCall(OpCodes.Call, ((PropertyInfo)getTargetMember).GetGetMethod(), null); } else { context.ExecMethodGenerator.EmitCall(OpCodes.Call, (MethodInfo)getTargetMember, null); } } // Load all parameters for (int i = 1; i <= context.Method.GetParameters().Length; i++) { context.ExecMethodGenerator.Emit(OpCodes.Ldarg, i); } // Call method and return context.ExecMethodGenerator.EmitCall(OpCodes.Call, targetMethod, null); context.ExecMethodGenerator.Emit(OpCodes.Ret); }