public virtual void GenerateMethod(PropertyInfo pi, MethodInfo mi, ILGenerator gen) { // Set default values for out parameters foreach (var par in mi.GetParameters().Where(p => p.IsOut)) { var defaultAttr = par.GetCustomAttributes(typeof(SafeDefaultAttribute), true) .Cast<SafeDefaultAttribute>().FirstOrDefault(); var type = par.ParameterType.GetElementType(); gen.EmitBestLdArg((ushort)(par.Position + 1)); if (defaultAttr!=null) defaultAttr.PushValueAction(gen); else PushDefaultReturnValue(gen, type); gen.EmitStoreToRef(type); } // Set default value for return types if (mi.ReturnType!=typeof(void)) { MemberInfo attrSource = mi; if (pi!=null) attrSource = pi; var defaultAttr = attrSource.GetCustomAttributes(typeof(SafeDefaultAttribute), true) .Cast<SafeDefaultAttribute>().FirstOrDefault(); if (defaultAttr!=null) defaultAttr.PushValueAction(gen); else PushDefaultReturnValue(gen, mi.ReturnType); } gen.Emit(OpCodes.Ret); }
public virtual 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 GenerateCall(IProxyModuleCoderAccess proxyModule, ILGenerator gen) { var pars = _adaptee.GetParameters(); var targetPars = _target.GetParameters(); var tokens = new object[pars.Length]; // Generate in conversions for (ushort i = 0; i < pars.Length; ++i) { // ReSharper disable once AccessToModifiedClosure tokens[i] = _paramBindings[i].GenerateInConversion(() => gen.EmitBestLdArg((ushort)(i + 1)), proxyModule, gen); } gen.Emit(OpCodes.Callvirt, _target); // Generate out conversions for (ushort i = 0; i < pars.Length; ++i) { // ReSharper disable once AccessToModifiedClosure _paramBindings[i].GenerateOutConversion(tokens[i], () => gen.EmitBestLdArg((ushort)(i + 1)), proxyModule, gen); } _retValBinding.GenerateConversion(proxyModule, gen); }
public virtual 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; }