Пример #1
0
        private static void CreateConstructor(HandlerClassBuildingContext classContext)
        {
            const int thisArgIndex           = 0;
            const int codecContainerArgIndex = 1;

            var constructorBuilder = classContext.Builder.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                CallingConventions.Standard, new[] { typeof(ICodecContainer) });
            var baseConstructor = typeof(object).GetConstructor(Type.EmptyTypes);
            var il = new MyILGenerator(constructorBuilder.GetILGenerator());

            il.Ldarg(thisArgIndex);
            il.Call(baseConstructor);
            il.Ldarg(thisArgIndex);
            il.Ldarg(codecContainerArgIndex);
            il.Stfld(classContext.Fields.CodecContainer);

            foreach (var manualCodecField in classContext.Fields.GetAllManualCodecFields())
            {
                il.Ldarg(thisArgIndex);
                il.Ldarg(codecContainerArgIndex);
                il.Call(CodecContainerMethods.GetManualCodecFor(manualCodecField.FieldType.GenericTypeArguments[0]));
                il.Stfld(manualCodecField);
            }

            il.Ret();
        }
Пример #2
0
        private void CreateConstructor(ProxyClassBuildingContext classContext, string path, ServiceDescription serviceDescription)
        {
            const int thisArgIndex            = 0;
            const int processorArgIndex       = 1;
            const int scopeArgIndex           = 2;
            const int timeoutSettingsArgIndex = 3;
            const int codecContainerArgIndex  = 4;

            var constructorBuilder = classContext.Builder.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                CallingConventions.Standard, ConstructorParameterTypes);
            var baseConstructor = typeof(object).GetConstructor(Type.EmptyTypes);
            var il = new MyILGenerator(constructorBuilder.GetILGenerator());

            il.Ldarg(thisArgIndex);
            il.Call(baseConstructor);
            il.Ldarg(thisArgIndex);
            il.Ldarg(processorArgIndex);
            il.Stfld(classContext.Fields.Processor);
            il.Ldarg(thisArgIndex);
            il.Ldarg(scopeArgIndex);
            il.Stfld(classContext.Fields.Scope);
            il.Ldarg(thisArgIndex);
            il.Ldarg(timeoutSettingsArgIndex);
            il.Stfld(classContext.Fields.TimeoutSettings);
            il.Ldarg(thisArgIndex);
            il.Ldarg(codecContainerArgIndex);
            il.Stfld(classContext.Fields.CodecContainer);

            foreach (var manualCodecField in classContext.Fields.GetAllManualCodecFields())
            {
                var type = manualCodecField.FieldType.GenericTypeArguments[0];
                ValidateManualCodecType(type);

                il.Ldarg(thisArgIndex);
                il.Ldarg(codecContainerArgIndex);
                il.Call(CodecContainerMethods.GetManualCodecFor(type));
                il.Stfld(manualCodecField);
            }

            foreach (var subserviceDesc in serviceDescription.Subservices)
            {
                var proxyClass   = CreateProxyClass(classContext.InterfaceType, subserviceDesc.Type, path + "/" + subserviceDesc.Name);
                var fieldBuilder = CreateSubserviceField(classContext, subserviceDesc, proxyClass);
                CreateSubserviceProperty(classContext, subserviceDesc, fieldBuilder);

                il.Ldarg(thisArgIndex);
                il.Ldarg(processorArgIndex);
                il.Ldarg(scopeArgIndex);
                il.Ldarg(timeoutSettingsArgIndex);
                il.Ldarg(codecContainerArgIndex);
                il.Newobj(proxyClass.GetConstructor(ConstructorParameterTypes));
                il.Stfld(fieldBuilder);
            }

            il.Ret();
        }
Пример #3
0
        protected override void EmitLoadMember(MyILGenerator il, Action <MyILGenerator> emitLoad, PropertyInfo member)
        {
            var propertyGetter = member.GetGetMethod(true);

            emitLoad(il);
            il.Call(propertyGetter);
        }
Пример #4
0
        private MethodInfo CreateDecodeDeferredMethod(ProxyClassBuildingContext classContext, string parentMethodName, IReadOnlyList <Type> genericTypeArguments, Type pureRetvalType)
        {
            var methodBuilder = classContext.Builder.DefineMethod("__rpc_decode_deferred_" + parentMethodName,
                                                                  MethodAttributes.Private | MethodAttributes.HideBySig);

            var genericTypeParameterBuilders = genericTypeArguments.Any()
                ? methodBuilder.DefineGenericParameters(genericTypeArguments.Select(x => x.Name).ToArray())
                : new GenericTypeParameterBuilder[0];
            var genericArgumentMap = genericTypeParameterBuilders.ToDictionary(x => x.Name, x => (Type)x);

            var retvalType = pureRetvalType.DeepSubstituteGenerics(genericArgumentMap);

            methodBuilder.SetParameters(DecodeDeferredParameterTypes);
            methodBuilder.SetReturnType(retvalType);
            methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed);

            var il = new MyILGenerator(methodBuilder.GetILGenerator());
            var emittingContext = new ProxyMethodEmittingContext(il, classContext.Fields);

            il.Ldarg(1);
            il.Call(TaskMethods.GetResult(typeof(byte[])));
            EmitPrepareToDecode(emittingContext);

            var retvalCodec = new ProxyMethodRetvalCodec(retvalType);

            retvalCodec.EmitDecode(emittingContext);
            il.Ret();

            return(methodBuilder);
        }
Пример #5
0
        private static Func <Type, string, string, Exception> CreateExceptionCreator()
        {
            var dynamicMethod = new DynamicMethod(
                "__srpc__CreateException",
                typeof(Exception), new[] { typeof(Type), typeof(string), typeof(string) },
                Assembly.GetExecutingAssembly().ManifestModule, true);
            var il = new MyILGenerator(dynamicMethod.GetILGenerator());

            il.Ldarg(0);                            // stack_0 = (Exception)FormatterServices.GetUninitializedObject(typeof(T))
            il.Call(GetUninitializedObject);
            il.Castclass(typeof(Exception));

            il.Dup();                               // stack_0.Init()
            il.Call(InitMethod);
            il.Dup();                               // stack_0._message = message
            il.Ldarg(1);
            il.Stfld(MessageField);
            il.Dup();                               // stack_0._message = message
            il.Ldarg(2);
            il.Stfld(RemoteStackTraceStringField);
            il.Ret();
            return((Func <Type, string, string, Exception>)dynamicMethod.CreateDelegate(typeof(Func <Type, string, string, Exception>)));
        }
Пример #6
0
        private static MethodBuilder CreateEncodeDeferredMethod(HandlerClassBuildingContext classContext, Type pureRetvalType)
        {
            const int taskArgIndex = 1;

            var methodBuilder = classContext.Builder.DefineMethod("EncodeDeferred",
                                                                  MethodAttributes.Private | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
                                                                  typeof(byte[]), new[] { typeof(Task <>).MakeGenericType(pureRetvalType) });

            var il = new MyILGenerator(methodBuilder.GetILGenerator());
            var emittingContext = new HandlerMethodEmittingContext(il, classContext.Fields);

            il.Ldarg(taskArgIndex);
            il.Call(TaskMethods.GetResult(pureRetvalType));
            EmitEncodeDirect(emittingContext, new HandlerParameterCodec[0], pureRetvalType);
            il.Ret();
            return(methodBuilder);
        }
Пример #7
0
        protected override void EmitSetMember(MyILGenerator il, PropertyInfo member)
        {
            var propertySetter = member.GetSetMethod(true);

            il.Call(propertySetter);
        }
Пример #8
0
 protected override void EmitParseFromString(MyILGenerator il)
 {
     il.Call(GetTypeMethod);
 }
Пример #9
0
        private void CreateMethod(ProxyClassBuildingContext classContext, string path, MethodDescription methodDesc)
        {
            var methodBuilder = classContext.Builder.DefineMethod(methodDesc.Name,
                                                                  MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                                                  MethodAttributes.NewSlot | MethodAttributes.Virtual);

            var genericTypeParameterBuilders = methodDesc.GenericParameters.Any()
                ? methodBuilder.DefineGenericParameters(methodDesc.GenericParameters.Select(x => x.Name).ToArray())
                : new GenericTypeParameterBuilder[0];
            var genericTypeParameterCodecs = genericTypeParameterBuilders.Select(x => new ProxyMethodGenericArgumentCodec(x)).ToArray();
            var genericArgumentMap         = genericTypeParameterBuilders.ToDictionary(x => x.Name, x => (Type)x);

            var parameterDescriptions         = methodDesc.Parameters.Select(x => x.DeepSubstituteGenerics(genericArgumentMap)).ToArray();
            var parameterTypesAdjustedForRefs = parameterDescriptions.Select(x => x.Way == MethodParameterWay.Val ? x.Type : x.Type.MakeByRefType()).ToArray();
            var allParameterCodecs            = parameterDescriptions.Select(x => new ProxyMethodParameterCodec(x)).ToArray();

            var retvalType = methodDesc.ReturnType.DeepSubstituteGenerics(genericArgumentMap);

            methodBuilder.SetParameters(parameterTypesAdjustedForRefs);
            methodBuilder.SetReturnType(retvalType);
            methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed);

            var il = new MyILGenerator(methodBuilder.GetILGenerator());
            var emittingContext = new ProxyMethodEmittingContext(il, classContext.Fields);

            var requestDataArrayVar = il.DeclareLocal(typeof(byte[]));                      // byte[] dataArray

            var requestParametersCodecs = allParameterCodecs.Where(x => x.IsRequestParameter).ToArray();

            if (requestParametersCodecs.Any() || genericTypeParameterBuilders.Any())
            {
                bool haveSizeOnStack = false;
                foreach (var codec in genericTypeParameterCodecs)
                {
                    codec.EmitCalculateSize(emittingContext);                               // stack_0 += CalculateSize(T_i)
                    EmitAddIf(il, ref haveSizeOnStack);
                }
                foreach (var parameter in requestParametersCodecs)
                {
                    parameter.EmitCalculateSize(emittingContext);                           // stack_0 += CalculateSize(arg_i)
                    EmitAddIf(il, ref haveSizeOnStack);
                }

                il.Newarr(typeof(byte));                                                    // dataArray = new byte[stack_0]
                il.Stloc(requestDataArrayVar);
                var pinnedVar = il.PinArray(typeof(byte), requestDataArrayVar);             // var pinned dataPointer = pin(dataArray)
                il.Ldloc(pinnedVar);                                                        // data = dataPointer
                il.Stloc(emittingContext.DataPointerVar);

                foreach (var codec in genericTypeParameterCodecs)
                {
                    codec.EmitEncode(emittingContext);                                      // Encode(T_i, data)
                }
                foreach (var codec in requestParametersCodecs)
                {
                    codec.EmitEncode(emittingContext);                                      // Encode(arg_i, data)
                }
            }
            else
            {
                il.Ldnull();                                                                // dataArray = null
                il.Stloc(requestDataArrayVar);
            }

            il.Ldarg(0);                                                                    // stack_0 = methodCallProcessor
            il.Ldfld(classContext.Fields.Processor);
            il.Ldtoken(classContext.InterfaceType);                                         // stack_1 = typeof(T)
            il.Call(TypeMethods.GetTypeFromHandle);
            il.Ldstr(string.Format("{0}/{1}", path, methodDesc.Name));                      // stack_2 = SuperServicePath/ServiceName/MethodName
            il.Ldarg(0);                                                                    // stack_3 = scope
            il.Ldfld(classContext.Fields.Scope);
            il.Ldloc(requestDataArrayVar);                                                  // stack_4 = dataArray
            il.Ldarg(0);                                                                    // stack_5 = timeoutSettings
            il.Ldfld(classContext.Fields.TimeoutSettings);

            var responseParameterCodecs = allParameterCodecs.Where(x => x.IsResponseParameter).ToArray();

            if (responseParameterCodecs.Any() && methodDesc.RemotingType != MethodRemotingType.Direct)
            {
                throw new ArgumentException(string.Format("Error processing {0} method: only direct methods can have Ref or Out parameters", path));
            }

            switch (methodDesc.RemotingType)
            {
            case MethodRemotingType.Direct:
                EmitProcessDirect(emittingContext, responseParameterCodecs, retvalType);
                break;

            case MethodRemotingType.AsyncVoid:
                EmitProcessAsyncVoid(il);
                break;

            case MethodRemotingType.AsyncWithRetval:
                EmitProcessAsyncWithRetval(classContext, emittingContext, methodDesc.Name, genericTypeParameterBuilders, retvalType);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            il.Ret();
        }