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); }
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); } }
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; }