示例#1
0
 public override void GenerateMethod(PropertyInfo pi, MethodInfo mi, ILGenerator gen)
 {
     if (_rsmc != null)
     {
         _rsmc.PutRealSubjectOnStack(gen);
     }
     else
     {
         gen.Emit(OpCodes.Ldnull);
     }
     gen.Emit(OpCodes.Ret);
 }
        public override void GenerateMethod(PropertyInfo pi, MethodInfo mi, ILGenerator gen)
        {
            _rsmc.PutRealSubjectOnStack(gen);
            var pars = mi.GetParameters();

            for (ushort i = 1; i <= pars.Length; ++i)
            {
                gen.EmitBestLdArg(i);
            }
            gen.Emit(OpCodes.Callvirt, mi);
            gen.Emit(OpCodes.Ret);
        }
示例#3
0
        public override void GenerateMethod(PropertyInfo pi, MethodInfo mi, ILGenerator gen)
        {
            var bestMatch = _bindings[mi];

            if (!bestMatch.Bindable)
            {
                gen.Emit(OpCodes.Ldstr, "");
                gen.Emit(OpCodes.Newobj, MissingMethodConstructor);
                gen.Emit(OpCodes.Throw);
            }
            else
            {
                _rsmc.PutRealSubjectOnStack(gen);
                bestMatch.GenerateCall(_proxyModule, gen);
                gen.Emit(OpCodes.Ret);
            }
        }
示例#4
0
        public override void GenerateMethod(PropertyInfo pi, MethodInfo mi, ILGenerator gen)
        {
            var methodInfo = _mapping[mi.GetMetadataToken()];

            if (!methodInfo.IsPublic)
            {
                var delegateField = _targetAccessType.GetField("_" + methodInfo.GetMetadataToken());
                gen.Emit(OpCodes.Ldsfld, delegateField);
                methodInfo = delegateField.FieldType.GetMethod("Invoke");
            }

            _rsmc.PutRealSubjectOnStack(gen);
            var pars = mi.GetParameters();

            for (ushort i = 1; i <= pars.Length; ++i)
            {
                gen.EmitBestLdArg(i);
            }
            gen.Emit(OpCodes.Callvirt, methodInfo);
            gen.Emit(OpCodes.Ret);
        }
        public override void GenerateMethod(PropertyInfo pi, MethodInfo mi, ILGenerator gen)
        {
            var smeType      = typeof(ISubjectMethodExists <>).MakeGenericType(_subjectType);
            var getSmeMethod = typeof(IMethodExistsProxyMeta).GetMethod("GetSubjectMethodExists").MakeGenericMethod(new[] { _subjectType });
            var dmeMethod    = smeType.GetMethod("DoesMethodExist", new[] { typeof(int) });

            // Locals
            var methodExistsProxyMetaLocal = gen.DeclareLocal(typeof(IMethodExistsProxyMeta));
            var subjectMethodExistsLocal   = gen.DeclareLocal(smeType);
            var makingSafeCallLocal        = gen.DeclareLocal(typeof(bool));

            // Labels
            var callOnRealSubjectLabel = gen.DefineLabel();
            var makeInnerSubjectCall   = gen.DefineLabel();
            var retLabel = gen.DefineLabel();

            // Check to see if the real subject supports method exists testing
            _rsmc.PutRealSubjectOnStack(gen);
            gen.Emit(OpCodes.Isinst, typeof(IMethodExistsProxyMeta));
            gen.Emit(OpCodes.Dup);
            gen.Emit(OpCodes.Stloc, methodExistsProxyMetaLocal);
            gen.Emit(OpCodes.Brfalse, callOnRealSubjectLabel);
            gen.Emit(OpCodes.Ldloc, methodExistsProxyMetaLocal);

            // It does - see if this method exists
            gen.Emit(OpCodes.Callvirt, getSmeMethod);
            gen.Emit(OpCodes.Dup);
            gen.Emit(OpCodes.Stloc, subjectMethodExistsLocal);
            gen.Emit(OpCodes.Brfalse_S, callOnRealSubjectLabel);
            gen.Emit(OpCodes.Ldloc, subjectMethodExistsLocal);
            gen.Emit(OpCodes.Ldc_I4, _methodIndex);
            gen.Emit(OpCodes.Callvirt, dmeMethod);
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Ceq, 0);
            gen.Emit(OpCodes.Stloc, makingSafeCallLocal);
            gen.Emit(OpCodes.Ldloc, makingSafeCallLocal);
            gen.Emit(OpCodes.Brfalse_S, callOnRealSubjectLabel);
            EmitCtorForSafeNullProxy(gen, _subjectType);
            gen.Emit(OpCodes.Br_S, makeInnerSubjectCall);

            // Prepare to call on the real subject
            gen.MarkLabel(callOnRealSubjectLabel);
            _rsmc.PutRealSubjectOnStack(gen);

            // Push arguments & call method on the inner subject (real or null proxy)
            gen.MarkLabel(makeInnerSubjectCall);
            var pars = mi.GetParameters();

            for (ushort i = 1; i <= pars.Length; ++i)
            {
                gen.EmitBestLdArg(i);
            }
            gen.Emit(OpCodes.Callvirt, mi);

            // If the method does not exist then the result is already safe and we can return
            gen.Emit(OpCodes.Ldloc, makingSafeCallLocal);
            gen.Emit(OpCodes.Brtrue_S, retLabel);

            // If the return type needs to be made safe then do so
            if (mi.ReturnType != typeof(void) && mi.ReturnType.IsInterface())
            {
                var notNullLabel = gen.DefineLabel();
                gen.Emit(OpCodes.Dup);                    // duplicate the return value on the stack
                gen.Emit(OpCodes.Brtrue_S, notNullLabel); // check it for null
                gen.Emit(OpCodes.Pop);                    // We don't need it - it's always null
                EmitCtorForSafeNullProxy(gen, mi.ReturnType);
                gen.Emit(OpCodes.Br_S, retLabel);
                gen.MarkLabel(notNullLabel);
                EmitCtorForSafeDirectProxy(gen, mi.ReturnType);
            }

            // Return
            gen.MarkLabel(retLabel);
            gen.Emit(OpCodes.Ret);

            ++_methodIndex;
        }