示例#1
0
        internal void EndSet(int i, Type stackType)
        {
            Debug.Assert(_paramTypes[i].IsByRef);
            var argType = _paramTypes[i].GetElementType();

            ProxyCodes.Convert(_il, stackType, argType, false);
            ProxyCodes.Stind(_il, argType);
        }
示例#2
0
 internal void EndSet(Type stackType)
 {
     ProxyCodes.Convert(_il, stackType, typeof(T), false);
     _il.Emit(OpCodes.Stelem_Ref);
 }
示例#3
0
        /// <summary> 添加方法实现 </summary>
        /// <param name="mi"></param>
        /// <returns></returns>
        private MethodBuilder AddMethodImpl(MethodInfo mi)
        {
            var parameters = mi.GetParameters();
            var paramTypes = ParamTypes(parameters, false);

            var mdb = _tb.DefineMethod(mi.Name, MethodAttributes.Public | MethodAttributes.Virtual, mi.ReturnType, paramTypes);

            if (mi.ContainsGenericParameters)
            {
                var ts = mi.GetGenericArguments();
                var ss = new string[ts.Length];
                for (var i = 0; i < ts.Length; i++)
                {
                    ss[i] = ts[i].Name;
                }
                var genericParameters = mdb.DefineGenericParameters(ss);
                for (var i = 0; i < genericParameters.Length; i++)
                {
                    genericParameters[i].SetGenericParameterAttributes(ts[i].GetTypeInfo().GenericParameterAttributes);
                }
            }
            var il = mdb.GetILGenerator();

            var args = new ParametersArray(il, paramTypes);

            // object[] args = new object[paramCount];
            il.Emit(OpCodes.Nop);
            var argsArr = new GenericArray <object>(il, ParamTypes(parameters, true).Length);

            for (var i = 0; i < parameters.Length; i++)
            {
                // args[i] = argi;
                if (parameters[i].IsOut)
                {
                    continue;
                }
                argsArr.BeginSet(i);
                args.Get(i);
                argsArr.EndSet(parameters[i].ParameterType);
            }

            // object[] packed = new object[PackedArgs.PackedTypes.Length];
            var packedArr = new GenericArray <object>(il, PackedArgs.PackedTypes.Length);

            // packed[PackedArgs.DispatchProxyPosition] = this;
            packedArr.BeginSet(PackedArgs.DispatchProxyPosition);
            il.Emit(OpCodes.Ldarg_0);
            packedArr.EndSet(typeof(ProxyExecutor));

            // packed[PackedArgs.DeclaringTypePosition] = typeof(iface);
            var typeGetTypeFromHandle = typeof(Type).GetRuntimeMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) });

            _assembly.GetTokenForMethod(mi, out var declaringType, out var methodToken);
            packedArr.BeginSet(PackedArgs.DeclaringTypePosition);
            il.Emit(OpCodes.Ldtoken, declaringType);
            il.Emit(OpCodes.Call, typeGetTypeFromHandle);
            packedArr.EndSet(typeof(object));

            // packed[PackedArgs.MethodTokenPosition] = iface method token;
            packedArr.BeginSet(PackedArgs.MethodTokenPosition);
            il.Emit(OpCodes.Ldc_I4, methodToken);
            packedArr.EndSet(typeof(int));

            // packed[PackedArgs.ArgsPosition] = args;
            packedArr.BeginSet(PackedArgs.ArgsPosition);
            argsArr.Load();
            packedArr.EndSet(typeof(object[]));

            // packed[PackedArgs.GenericTypesPosition] = mi.GetGenericArguments();
            if (mi.ContainsGenericParameters)
            {
                packedArr.BeginSet(PackedArgs.GenericTypesPosition);
                var genericTypes = mi.GetGenericArguments();
                var typeArr      = new GenericArray <Type>(il, genericTypes.Length);
                for (var i = 0; i < genericTypes.Length; ++i)
                {
                    typeArr.BeginSet(i);
                    il.Emit(OpCodes.Ldtoken, genericTypes[i]);
                    il.Emit(OpCodes.Call, typeGetTypeFromHandle);
                    typeArr.EndSet(typeof(Type));
                }
                typeArr.Load();
                packedArr.EndSet(typeof(Type[]));
            }

            for (var i = 0; i < parameters.Length; i++)
            {
                if (!parameters[i].ParameterType.IsByRef)
                {
                    continue;
                }
                args.BeginSet(i);
                argsArr.Get(i);
                args.EndSet(i, typeof(object));
            }

            var invokeMethod = SDelegateInvoke;

            if (IsGenericTask(mi.ReturnType))
            {
                var returnTypes = mi.ReturnType.GetGenericArguments();
                invokeMethod = SDelegateinvokeAsyncT.MakeGenericMethod(returnTypes);
            }
            else if (mi.ReturnType == typeof(Task))
            {
                invokeMethod = SDelegateInvokeAsync;
            }
            else if (mi.ReturnType != typeof(void))
            {
                var returnType = mi.ReturnType;
                invokeMethod = SDelegateInvokeT.MakeGenericMethod(returnType);
            }

            // Call AsyncDispatchProxyGenerator.Invoke(object[]), InvokeAsync or InvokeAsyncT
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, _fields[InvokeActionFieldAndCtorParameterIndex]);
            packedArr.Load();
            il.Emit(OpCodes.Callvirt, invokeMethod);
            if (mi.ReturnType != typeof(void))
            {
                ProxyCodes.Convert(il, typeof(object), mi.ReturnType, false);
            }
            else
            {
                il.Emit(OpCodes.Pop);
            }

            il.Emit(OpCodes.Ret);

            _tb.DefineMethodOverride(mdb, mi);
            return(mdb);
        }