DefineMethodOverride() public method

public DefineMethodOverride ( MethodInfo baseMethod ) : ILGen
baseMethod System.Reflection.MethodInfo
return ILGen
        // This generates a method like the following:
        //
        //  TrySetExtraValue(object name, object value) {
        //      if (name1 == name) {
        //          type.name1Slot = value;
        //          return 1;
        //      }
        //      if (name2 == name) {
        //          type.name2Slot = value;
        //          return 1;
        //      }
        //      ...
        //      return 0
        //  }

        private void MakeSetMethod()
        {
            MethodInfo baseMethod = typeof(CustomSymbolDictionary).GetMethod("TrySetExtraValue", BindingFlags.NonPublic | BindingFlags.Instance);
            ILGen      cg         = TypeGen.DefineMethodOverride(baseMethod);

            foreach (KeyValuePair <GlobalVariableExpression, FieldBuilder> kv in _fields)
            {
                SymbolId name = SymbolTable.StringToId(kv.Key.Name);

                EmitSymbolId(cg, name);
                // arg0 -> this
                cg.EmitLoadArg(1);
                cg.EmitCall(typeof(SymbolId), "op_Equality");

                Label next = cg.DefineLabel();
                cg.Emit(OpCodes.Brfalse_S, next);

                cg.EmitFieldGet(kv.Value);
                cg.EmitLoadArg(2);
                cg.EmitPropertySet(typeof(ModuleGlobalWrapper), "CurrentValue");

                cg.EmitInt(1);
                cg.Emit(OpCodes.Ret);
                cg.MarkLabel(next);
            }
            cg.EmitInt(0);
            cg.Emit(OpCodes.Ret);
        }
        //
        // This generates a method like the following:
        //
        //  TryGetExtraValue(int name, object out value) {
        //      if (name1 == name) {
        //          value = type.name1Slot.RawValue;
        //          return value != Uninitialized.Instance;
        //      }
        //      if (name2 == name) {
        //          value = type.name2Slot.RawValue;
        //          return value != Uninitialized.Instance;
        //      }
        //      ...
        //      return false
        //  }

        private void MakeGetMethod()
        {
            MethodInfo baseMethod = typeof(CustomSymbolDictionary).GetMethod("TryGetExtraValue", BindingFlags.NonPublic | BindingFlags.Instance);
            ILGen      cg         = TypeGen.DefineMethodOverride(baseMethod);

            foreach (KeyValuePair <GlobalVariableExpression, FieldBuilder> kv in _fields)
            {
                SymbolId name = SymbolTable.StringToId(kv.Key.Name);

                EmitSymbolId(cg, name);
                // arg0 -> this
                cg.EmitLoadArg(1);
                cg.EmitCall(typeof(SymbolId), "op_Equality");

                Label next = cg.DefineLabel();
                cg.Emit(OpCodes.Brfalse_S, next);

                cg.EmitLoadArg(2);

                // Expects to push as an object.
                EmitGetRawFromObject(cg, kv.Value);
                cg.Emit(OpCodes.Stind_Ref);

                EmitGetRawFromObject(cg, kv.Value);
                cg.EmitFieldGet(typeof(Uninitialized), "Instance");
                cg.Emit(OpCodes.Ceq);
                cg.Emit(OpCodes.Not);
                cg.Emit(OpCodes.Ret);
                cg.MarkLabel(next);
            }
            cg.EmitInt(0);
            cg.Emit(OpCodes.Ret);
        }
        private static void EmitOverrideGetHashCode(TypeGen typeGen) {
            Type baseType = typeGen.TypeBuilder.BaseType;
            MethodInfo baseMethod = baseType.GetMethod("GetHashCode", Type.EmptyTypes);
            Compiler cg = typeGen.DefineMethodOverride(baseMethod);

            // Check if a "hash" method exists on this class
            cg.EmitType(typeGen.TypeBuilder);
            cg.EmitString("hash");
            cg.EmitCall(typeof(RubyOps).GetMethod("ResolveDeclaredInstanceMethod"));
            Label callBase = cg.DefineLabel();
            cg.Emit(OpCodes.Brfalse_S, callBase);

            // If so, call it
            cg.EmitThis();
            cg.EmitCall(typeof(RubyOps).GetMethod("CallHash"));
            cg.EmitReturn();

            // Otherwise, call base class
            cg.MarkLabel(callBase);
            cg.EmitThis();
            cg.Emit(OpCodes.Call, baseMethod); // base call must be non-virtual
            cg.EmitReturn();

            cg.Finish();
        }
        // we need to get the right execution context
#if OBSOLETE
        private static void EmitOverrideEquals(TypeGen typeGen) {
            Type baseType = typeGen.TypeBuilder.BaseType;
            MethodInfo baseMethod = baseType.GetMethod("Equals", new Type[] { typeof(object) });
            Compiler cg = typeGen.DefineMethodOverride(baseMethod);

            // Check if an "eql?" method exists on this class
            cg.EmitType(typeGen.TypeBuilder);
            cg.EmitString("eql?");
            cg.EmitCall(typeof(RubyOps).GetMethod("ResolveDeclaredInstanceMethod"));
            Label callBase = cg.DefineLabel();
            cg.Emit(OpCodes.Brfalse_S, callBase);

            // If so, call it
            cg.EmitThis();
            cg.EmitArgGet(0);
            cg.EmitCall(typeof(RubyOps).GetMethod("CallEql"));
            cg.EmitReturn();

            // Otherwise, call base class
            cg.MarkLabel(callBase);
            cg.EmitThis();
            cg.EmitArgGet(0);
            cg.Emit(OpCodes.Call, baseMethod); // base call must be non-virtual
            cg.EmitReturn();

            cg.Finish();
        }