private void AddVoidMethodImplementation(
            TypeBuilder classBuilder,
            int interfaceDescriptionId,
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes,
            string interfaceName)
        {
            var interfaceMethod = methodDescription.MethodInfo;

            var methodBuilder = CodeBuilderUtils.CreateExplitInterfaceMethodBuilder(
                classBuilder,
                interfaceMethod);

            var ilGen = methodBuilder.GetILGenerator();

            // Create Wrapped Request
            LocalBuilder wrappedRequestBody =
                CreateWrappedRequestBody(methodDescription, methodBodyTypes, ilGen, methodDescription.MethodInfo.GetParameters());

            this.AddVoidMethodImplementation(
                ilGen,
                interfaceDescriptionId,
                methodDescription,
                wrappedRequestBody,
                interfaceName);

            ilGen.Emit(OpCodes.Ret);
        }
Exemple #2
0
        public CodeBuilderContext(string assemblyName, string assemblyNamespace, bool enableDebugging = false)
        {
            this.AssemblyNamespace = assemblyNamespace;
            this.enableDebugging   = enableDebugging;

            this.AssemblyBuilder = CodeBuilderUtils.CreateAssemblyBuilder(assemblyName, this.enableDebugging);
            this.ModuleBuilder   = CodeBuilderUtils.CreateModuleBuilder(this.AssemblyBuilder, assemblyName, this.enableDebugging);
        }
        private Type BuildProxyActivatorType(
            CodeBuilderContext context,
            Type proxyInterfaceType,
            Type proxyType)
        {
            var classBuilder = CodeBuilderUtils.CreateClassBuilder(
                context.ModuleBuilder,
                ns: context.AssemblyNamespace,
                className: this.CodeBuilder.Names.GetProxyActivatorClassName(proxyInterfaceType),
                interfaces: new[] { typeof(IProxyActivator) });

            AddCreateInstanceMethod(classBuilder, proxyType);
            return(classBuilder.CreateTypeInfo().AsType());
        }
        private Type BuildProxyType(
            CodeBuilderContext context,
            Type proxyInterfaceType,
            IDictionary <InterfaceDescription, MethodBodyTypesBuildResult> methodBodyTypesResultsMap)
        {
            var classBuilder = CodeBuilderUtils.CreateClassBuilder(
                context.ModuleBuilder,
                ns: context.AssemblyNamespace,
                className: this.CodeBuilder.Names.GetProxyClassName(proxyInterfaceType),
                baseType: this.proxyBaseType,
                interfaces: methodBodyTypesResultsMap.Select(item => item.Key.InterfaceType).ToArray());

            this.AddGetReturnValueMethod(classBuilder, methodBodyTypesResultsMap);
            this.AddInterfaceImplementations(classBuilder, methodBodyTypesResultsMap);

            return(classBuilder.CreateTypeInfo().AsType());
        }
        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));
        }
        private void AddGetReturnValueMethod(
            TypeBuilder classBuilder,
            IDictionary <InterfaceDescription, MethodBodyTypesBuildResult> methodBodyTypesResultsMap)
        {
            var methodBuilder = CodeBuilderUtils.CreateProtectedMethodBuilder(
                classBuilder,
                "GetReturnValue",
                typeof(object),  // return value from the reponseBody
                typeof(int),     // interfaceId
                typeof(int),     // methodId
                typeof(object)); // responseBody

            var ilGen = methodBuilder.GetILGenerator();

            foreach (var item in methodBodyTypesResultsMap)
            {
                var interfaceDescription = item.Key;
                var methodBodyTypesMap   = item.Value.MethodBodyTypesMap;

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

                    var elseLabel = ilGen.DefineLabel();

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

                    ilGen.MarkLabel(elseLabel);
                }
            }

            // return null; (if method id's and interfaceId do not mGetReturnValueatch)
            ilGen.Emit(OpCodes.Ldnull);
            ilGen.Emit(OpCodes.Ret);
        }
        private static Type BuildResponseBodyType(
            ICodeBuilderNames codeBuilderNames,
            CodeBuilderContext context,
            MethodDescription methodDescription)
        {
            var responseBodyTypeBuilder = CodeBuilderUtils.CreateDataContractTypeBuilder(
                moduleBuilder: context.ModuleBuilder,
                ns: context.AssemblyNamespace,
                typeName: codeBuilderNames.GetResponseBodyTypeName(methodDescription.Name),
                dcNamespace: codeBuilderNames.GetDataContractNamespace());

            var returnDataType = methodDescription.ReturnType.GetGenericArguments()[0];

            CodeBuilderUtils.AddDataMemberField(
                dcTypeBuilder: responseBodyTypeBuilder,
                fieldType: returnDataType,
                fieldName: codeBuilderNames.RetVal);

            return(responseBodyTypeBuilder.CreateTypeInfo().AsType());
        }
        private static Type BuildRequestBodyType(
            ICodeBuilderNames codeBuilderNames,
            CodeBuilderContext context,
            MethodDescription methodDescription)
        {
            var requestBodyTypeBuilder = CodeBuilderUtils.CreateDataContractTypeBuilder(
                moduleBuilder: context.ModuleBuilder,
                ns: context.AssemblyNamespace,
                typeName: codeBuilderNames.GetRequestBodyTypeName(methodDescription.Name),
                dcNamespace: codeBuilderNames.GetDataContractNamespace());

            foreach (var argument in methodDescription.Arguments)
            {
                CodeBuilderUtils.AddDataMemberField(
                    dcTypeBuilder: requestBodyTypeBuilder,
                    fieldType: argument.ArgumentType,
                    fieldName: argument.Name);
            }

            return(requestBodyTypeBuilder.CreateTypeInfo().AsType());
        }
        public MethodDispatcherBuildResult Build(
            InterfaceDescription interfaceDescription)
        {
            var context = new CodeBuilderContext(
                assemblyName: this.CodeBuilder.Names.GetMethodDispatcherAssemblyName(interfaceDescription.InterfaceType),
                assemblyNamespace: this.CodeBuilder.Names.GetMethodDispatcherAssemblyNamespace(interfaceDescription
                                                                                               .InterfaceType),
                enableDebugging: CodeBuilderAttribute.IsDebuggingEnabled(interfaceDescription.InterfaceType));

            var result = new MethodDispatcherBuildResult(context);

            // ensure that the method body types are built
            var methodBodyTypesBuildResult =
                this.CodeBuilder.GetOrBuildMethodBodyTypes(interfaceDescription.InterfaceType);

            // build dispatcher class
            var classBuilder = CodeBuilderUtils.CreateClassBuilder(
                context.ModuleBuilder,
                ns: context.AssemblyNamespace,
                className: this.CodeBuilder.Names.GetMethodDispatcherClassName(interfaceDescription.InterfaceType),
                baseType: this.methodDispatcherBaseType);

            this.AddCreateResponseBodyMethod(classBuilder, interfaceDescription, methodBodyTypesBuildResult);
            this.AddOnDispatchAsyncMethod(classBuilder, interfaceDescription, methodBodyTypesBuildResult);
            this.AddOnDispatchMethod(classBuilder, interfaceDescription, methodBodyTypesBuildResult);

            var methodNameMap = GetMethodNameMap(interfaceDescription);

            // create the dispatcher type, instantiate and initialize it
            result.MethodDispatcherType = classBuilder.CreateTypeInfo().AsType();
            result.MethodDispatcher     = (TMethodDispatcher)Activator.CreateInstance(result.MethodDispatcherType);
            var v2MethodDispatcherBase = (ActorMethodDispatcherBase)result.MethodDispatcher;

            v2MethodDispatcherBase.Initialize(interfaceDescription, methodNameMap);

            context.Complete();
            return(result);
        }
        private static void AddCreateInstanceMethod(
            TypeBuilder classBuilder,
            Type proxyType)
        {
            var methodBuilder = CodeBuilderUtils.CreatePublicMethodBuilder(
                classBuilder,
                "CreateInstance",
                typeof(IActorProxy));

            var ilGen     = methodBuilder.GetILGenerator();
            var proxyCtor = proxyType.GetConstructor(Type.EmptyTypes);

            if (proxyCtor != null)
            {
                ilGen.Emit(OpCodes.Newobj, proxyCtor);
                ilGen.Emit(OpCodes.Ret);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldnull);
                ilGen.Emit(OpCodes.Ret);
            }
        }
        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);
        }
        private void AddAsyncMethodImplementation(
            TypeBuilder classBuilder,
            int interfaceId,
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes,
            string interfaceName)
        {
            var interfaceMethod = methodDescription.MethodInfo;
            var parameters      = interfaceMethod.GetParameters();
            var methodBuilder   = CodeBuilderUtils.CreateExplitInterfaceMethodBuilder(
                classBuilder,
                interfaceMethod);
            var ilGen           = methodBuilder.GetILGenerator();
            var parameterLength = parameters.Length;

            if (methodDescription.HasCancellationToken)
            {
                // Cancellation token is tracked locally and should not be serialized and sent
                // as a part of the request body.
                parameterLength -= 1;
            }

            LocalBuilder requestMessage = null;

            if (parameterLength > 0)
            {
                // Create Wrapped Message
                // create requestBody and assign the values to its field from the arguments
                var wrappedRequestBody = CreateWrappedRequestBody(methodDescription, methodBodyTypes, ilGen, parameters);

                // create IServiceRemotingRequestMessageBody message
                requestMessage = this.CreateRequestRemotingMessageBody(methodDescription, interfaceName, ilGen, parameterLength, wrappedRequestBody);

                // Check if requestMessage is not implementing WrappedMessage , then call SetParam
                this.SetParameterIfNeeded(ilGen, requestMessage, parameterLength, parameters);
            }

            var objectTask = ilGen.DeclareLocal(typeof(Task <IActorResponseMessageBody>));

            // call the base InvokeMethodAsync method
            ilGen.Emit(OpCodes.Ldarg_0);                       // base
            ilGen.Emit(OpCodes.Ldc_I4, interfaceId);           // interfaceId
            ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id);  // methodId
            ilGen.Emit(OpCodes.Ldstr, methodDescription.Name); // method name

            if (requestMessage != null)
            {
                ilGen.Emit(OpCodes.Ldloc, requestMessage);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldnull);
            }

            // Cancellation token argument
            if (methodDescription.HasCancellationToken)
            {
                // Last argument should be the cancellation token
                var cancellationTokenArgIndex = parameters.Length;
                ilGen.Emit(OpCodes.Ldarg, cancellationTokenArgIndex);
            }
            else
            {
                var cancellationTokenNone = typeof(CancellationToken).GetMethod("get_None");
                ilGen.EmitCall(OpCodes.Call, cancellationTokenNone, null);
            }

            ilGen.EmitCall(OpCodes.Call, this.invokeAsyncMethodInfo, null);
            ilGen.Emit(OpCodes.Stloc, objectTask);

            // call the base method to get the continuation task and
            // convert the response body to return value when the task is finished
            if (TypeUtility.IsTaskType(methodDescription.ReturnType) &&
                methodDescription.ReturnType.GetTypeInfo().IsGenericType)
            {
                var retvalType = methodDescription.ReturnType.GetGenericArguments()[0];

                ilGen.Emit(OpCodes.Ldarg_0);                      // base pointer
                ilGen.Emit(OpCodes.Ldc_I4, interfaceId);          // interfaceId
                ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id); // methodId
                ilGen.Emit(OpCodes.Ldloc, objectTask);            // task<IServiceRemotingResponseMessageBody>
                ilGen.Emit(OpCodes.Call, this.continueWithResultMethodInfo.MakeGenericMethod(retvalType));
                ilGen.Emit(OpCodes.Ret);                          // return base.ContinueWithResult<TResult>(task);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldarg_0);           // base pointer
                ilGen.Emit(OpCodes.Ldloc, objectTask); // task<object>
                ilGen.Emit(OpCodes.Call, this.continueWithMethodInfo);
                ilGen.Emit(OpCodes.Ret);               // return base.ContinueWith(task);
            }
        }