Пример #1
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>)));
        }
Пример #2
0
        private static void CreateMethodDelegate(HandlerClassBuildingContext classContext)
        {
            const int implementationArgIndex = 1;
            const int dataArgIndex           = 2;
            const int offsetArgIndex         = 3;

            var methodBuilder = classContext.Builder.DefineMethod("Handle",
                                                                  MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                                                  MethodAttributes.NewSlot | MethodAttributes.Virtual,
                                                                  typeof(Task <byte[]>), new[] { typeof(object), typeof(byte[]), typeof(int) });

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

            var serviceDescriptionChain = classContext.ServiceDescriptionChain;

            il.Ldarg(implementationArgIndex);                                       // stack_0 = (TServiceImplementation) arg_1
            il.Castclass(serviceDescriptionChain.First().Type);

            for (int i = 0; i < serviceDescriptionChain.Count - 1; i++)
            {
                var current = serviceDescriptionChain[i];
                var next    = serviceDescriptionChain[i + 1];
                il.Callvirt(current.Type.GetProperty(next.Name).GetGetMethod());    // stack_0 = stack_0.Property
            }

            var methodDescription = classContext.MethodDescription;

            var genericArgumentMap = methodDescription.GenericParameters
                                     .Zip(classContext.GenericTypeParameterBuilders, (p, a) => new KeyValuePair <string, Type>(p.Name, a))
                                     .ToDictionary(x => x.Key, x => x.Value);

            var parameterDescriptions = methodDescription.Parameters.Select(x => x.DeepSubstituteGenerics(genericArgumentMap)).ToArray();
            var retvalType            = methodDescription.ReturnType.DeepSubstituteGenerics(genericArgumentMap);

            var allParameterCodecs      = parameterDescriptions.Select((x, i) => new HandlerParameterCodec(emittingContext, x)).ToArray();
            var requestParameterCodecs  = allParameterCodecs.Where(x => x.IsRequestParameter).ToArray();
            var responseParameterCodecs = allParameterCodecs.Where(x => x.IsResponseParameter).ToArray();

            if (requestParameterCodecs.Any())
            {
                il.Ldarg(dataArgIndex);                                 // remainingBytes = dataArray.Length - offset
                il.Ldlen();
                il.Ldarg(offsetArgIndex);
                il.Sub();
                il.Stloc(emittingContext.RemainingBytesVar);
                var pinnedVar = il.PinArray(typeof(byte), 2);           // var pinned dataPointer = pin(dataArray)
                il.Ldloc(pinnedVar);                                    // data = dataPointer + offset
                il.Ldarg(offsetArgIndex);
                il.Add();
                il.Stloc(emittingContext.DataPointerVar);
            }

            foreach (var codec in allParameterCodecs)
            {
                codec.EmitDecodeAndPrepare();
            }

            // ReSharper disable CoVariantArrayConversion
            var resolvedMethodInfo = classContext.GenericTypeParameterBuilders.Any()
                ? methodDescription.MethodInfo.MakeGenericMethod(classContext.GenericTypeParameterBuilders)
                : methodDescription.MethodInfo;

            il.Callvirt(resolvedMethodInfo);                            // stack_0 = stack_0.Method(stack_1, stack_2, ...)
            // ReSharper restore CoVariantArrayConversion

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

            case MethodRemotingType.AsyncVoid:
                EmitProcessAndEncodeAsyncVoid(emittingContext);
                break;

            case MethodRemotingType.AsyncWithRetval:
                EmitProcessAndEncodeAsyncWithRetval(classContext, emittingContext, retvalType.GetGenericArguments()[0]);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            il.Ret();
        }