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 void AddVoidMethodImplementation( TypeBuilder classBuilder, int interfaceId, MethodDescription methodDescription, MethodBodyTypes methodBodyTypes) { var interfaceMethod = methodDescription.MethodInfo; var parameters = interfaceMethod.GetParameters(); var methodBuilder = CodeBuilderUtils.CreateExplitInterfaceMethodBuilder( classBuilder, interfaceMethod); var ilGen = methodBuilder.GetILGenerator(); LocalBuilder requestBody = null; if (methodBodyTypes.RequestBodyType != null) { // create requestBody and assign the values to its field from the arguments requestBody = ilGen.DeclareLocal(methodBodyTypes.RequestBodyType); var requestBodyCtor = methodBodyTypes.RequestBodyType.GetConstructor(Type.EmptyTypes); if (requestBodyCtor != null) { ilGen.Emit(OpCodes.Newobj, requestBodyCtor); ilGen.Emit(OpCodes.Stloc, requestBody); for (var i = 0; i < parameters.Length; i++) { ilGen.Emit(OpCodes.Ldloc, requestBody); ilGen.Emit(OpCodes.Ldarg, i + 1); ilGen.Emit(OpCodes.Stfld, methodBodyTypes.RequestBodyType.GetField(parameters[i].Name)); } } } // call the base Invoke method ilGen.Emit(OpCodes.Ldarg_0); // base ilGen.Emit(OpCodes.Ldc_I4, interfaceId); // interfaceId ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id); // methodId if (requestBody != null) { ilGen.Emit(OpCodes.Ldloc, requestBody); } else { ilGen.Emit(OpCodes.Ldnull); } ilGen.EmitCall(OpCodes.Call, this.invokeMethodInfo, null); ilGen.Emit(OpCodes.Ret); }
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 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 match) ilGen.Emit(OpCodes.Ldnull); ilGen.Emit(OpCodes.Ret); }
private void AddOnDispatchAsyncMethod( TypeBuilder classBuilder, InterfaceDescription interfaceDescription, MethodBodyTypesBuildResult methodBodyTypesBuildResult) { var dispatchMethodImpl = CodeBuilderUtils.CreateProtectedMethodBuilder( classBuilder, "OnDispatchAsync", typeof(Task <object>), typeof(int), // methodid typeof(object), // remoted object typeof(object), // requestBody 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, methodBodyTypes: methodBodyTypesBuildResult.MethodBodyTypesMap[methodDescription.Name]); ilGen.MarkLabel(elseLable); } ilGen.ThrowException(typeof(MissingMethodException)); }
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()); }
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()); }
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); result.MethodDispatcher.Initialize( interfaceDescription.Id, methodNameMap, methodBodyTypesBuildResult.GetRequestBodyTypes(), methodBodyTypesBuildResult.GetResponseBodyTypes()); context.Complete(); return(result); }
private static void AddCreateInstanceMethod( TypeBuilder classBuilder, Type proxyType) { var methodBuilder = CodeBuilderUtils.CreatePublicMethodBuilder( classBuilder, "CreateInstance", typeof(ProxyBase)); 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, "CreateResponseBody", 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) { var interfaceMethod = methodDescription.MethodInfo; var parameters = interfaceMethod.GetParameters(); var methodBuilder = CodeBuilderUtils.CreateExplitInterfaceMethodBuilder( classBuilder, interfaceMethod); var ilGen = methodBuilder.GetILGenerator(); LocalBuilder requestBody = null; if (methodBodyTypes.RequestBodyType != null) { // create requestBody and assign the values to its field from the arguments requestBody = ilGen.DeclareLocal(methodBodyTypes.RequestBodyType); var requestBodyCtor = methodBodyTypes.RequestBodyType.GetConstructor(Type.EmptyTypes); if (requestBodyCtor != null) { ilGen.Emit(OpCodes.Newobj, requestBodyCtor); ilGen.Emit(OpCodes.Stloc, requestBody); var argsLength = parameters.Length; if (methodDescription.HasCancellationToken) { // Cancellation token is tracked locally and should not be serialized and sent // as a part of the request body. argsLength = argsLength - 1; } for (var i = 0; i < argsLength; i++) { ilGen.Emit(OpCodes.Ldloc, requestBody); ilGen.Emit(OpCodes.Ldarg, i + 1); ilGen.Emit(OpCodes.Stfld, methodBodyTypes.RequestBodyType.GetField(parameters[i].Name)); } } } var objectTask = ilGen.DeclareLocal(typeof(Task <object>)); // call the base InvokeAsync method ilGen.Emit(OpCodes.Ldarg_0); // base ilGen.Emit(OpCodes.Ldc_I4, interfaceId); // interfaceId ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id); // methodId if (requestBody != null) { ilGen.Emit(OpCodes.Ldloc, requestBody); } 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 (methodBodyTypes.ResponseBodyType != null) { 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<object> 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); } }