public void UpdateKnownTypeDetail(InterfaceDescription interfaceDescription, MethodBodyTypesBuildResult methodBodyTypesBuildResult)
        {
            var responseKnownTypes = new List <Type>();
            var requestKnownType   = new List <Type>();

            foreach (var entry in interfaceDescription.Methods)
            {
                if (TypeUtility.IsTaskType(entry.ReturnType) && entry.ReturnType.GetTypeInfo().IsGenericType)
                {
                    var returnType = entry.MethodInfo.ReturnType.GetGenericArguments()[0];
                    if (!responseKnownTypes.Contains(returnType))
                    {
                        responseKnownTypes.Add(returnType);
                    }
                }

                requestKnownType.AddRange(entry.MethodInfo.GetParameters()
                                          .ToList()
                                          .Select(p => p.ParameterType)
                                          .Except(requestKnownType));
            }

            var knownType = new InterfaceDetails
            {
                Id = interfaceDescription.Id,
                ServiceInterfaceType      = interfaceDescription.InterfaceType,
                RequestKnownTypes         = requestKnownType,
                ResponseKnownTypes        = responseKnownTypes,
                MethodNames               = interfaceDescription.Methods.ToDictionary(item => item.Name, item => item.Id),
                RequestWrappedKnownTypes  = methodBodyTypesBuildResult.GetRequestBodyTypes(),
                ResponseWrappedKnownTypes = methodBodyTypesBuildResult.GetResponseBodyTypes(),
            };

            this.UpdateKnownTypes(interfaceDescription.Id, interfaceDescription.InterfaceType.FullName, knownType);
        }
        private void AddOnDispatchAsyncMethod(
            TypeBuilder classBuilder,
            InterfaceDescription interfaceDescription,
            MethodBodyTypesBuildResult methodBodyTypesBuildResult)
        {
            var dispatchMethodImpl = CodeBuilderUtils.CreateProtectedMethodBuilder(
                classBuilder,
                "OnDispatchAsync",
                typeof(Task <IActorResponseMessageBody>),
                typeof(int),                      // methodid
                typeof(object),                   // remoted object
                typeof(IActorRequestMessageBody), // requestBody
                typeof(IActorMessageBodyFactory), // remotingmessageBodyFactory
                typeof(CancellationToken));       // CancellationToken

            var ilGen = dispatchMethodImpl.GetILGenerator();

            var castedObject = ilGen.DeclareLocal(interfaceDescription.InterfaceType);

            ilGen.Emit(OpCodes.Ldarg_2);             // load remoted object
            ilGen.Emit(OpCodes.Castclass, interfaceDescription.InterfaceType);
            ilGen.Emit(OpCodes.Stloc, castedObject); // store casted result to local 0

            foreach (var methodDescription in interfaceDescription.Methods)
            {
                if (!TypeUtility.IsTaskType(methodDescription.ReturnType))
                {
                    continue;
                }

                var elseLable = ilGen.DefineLabel();

                this.AddIfMethodIdInvokeAsyncBlock(
                    ilGen: ilGen,
                    elseLabel: elseLable,
                    castedObject: castedObject,
                    methodDescription: methodDescription,
                    interfaceName: interfaceDescription.InterfaceType.FullName,
                    methodBodyTypes: methodBodyTypesBuildResult.MethodBodyTypesMap[methodDescription.Name]);

                ilGen.MarkLabel(elseLable);
            }

            ilGen.ThrowException(typeof(MissingMethodException));
        }
Пример #3
0
        public MethodBodyTypesBuildResult Build(InterfaceDescription interfaceDescription)
        {
            var context = new CodeBuilderContext(
                assemblyName: this.CodeBuilder.Names.GetMethodBodyTypesAssemblyName(interfaceDescription.InterfaceType),
                assemblyNamespace: this.CodeBuilder.Names.GetMethodBodyTypesAssemblyNamespace(interfaceDescription.InterfaceType),
                enableDebugging: CodeBuilderAttribute.IsDebuggingEnabled(interfaceDescription.InterfaceType));

            var result = new MethodBodyTypesBuildResult(context)
            {
                MethodBodyTypesMap = new Dictionary <string, MethodBodyTypes>(),
            };

            foreach (var method in interfaceDescription.Methods)
            {
                result.MethodBodyTypesMap.Add(
                    method.Name,
                    Build(this.CodeBuilder.Names, context, method));
            }

            context.Complete();
            return(result);
        }
        private void AddCreateResponseBodyMethod(
            TypeBuilder classBuilder,
            InterfaceDescription interfaceDescription,
            MethodBodyTypesBuildResult methodBodyTypesBuildResult)
        {
            var methodBuilder = CodeBuilderUtils.CreateProtectedMethodBuilder(
                classBuilder,
                "CreateWrappedResponseBody",
                typeof(object),  // responseBody - return value
                typeof(int),     // methodId
                typeof(object)); // retval from the invoked method on the remoted object

            var ilGen = methodBuilder.GetILGenerator();

            foreach (var methodDescription in interfaceDescription.Methods)
            {
                var methodBodyTypes = methodBodyTypesBuildResult.MethodBodyTypesMap[methodDescription.Name];
                if (methodBodyTypes.ResponseBodyType == null)
                {
                    continue;
                }

                var elseLabel = ilGen.DefineLabel();

                this.AddIfMethodIdCreateResponseBlock(
                    ilGen,
                    elseLabel,
                    methodDescription.Id,
                    methodBodyTypes.ResponseBodyType);

                ilGen.MarkLabel(elseLabel);
            }

            // return null; (if method id's do not match)
            ilGen.Emit(OpCodes.Ldnull);
            ilGen.Emit(OpCodes.Ret);
        }