private Type CreateProxyClass(Type rootType, Type type, string path) { var serviceDescription = serviceDescriptionBuilder.Build(type); path = path ?? serviceDescription.Name; var typeBuilder = moduleBuilder.DefineType("__rpc_proxy_" + type.FullName + "_" + classNameDisambiguator++, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class, typeof(object), new[] { type }); #region Emit Fields var processorField = typeBuilder.DefineField("methodCallProcessor", typeof(IOutgoingMethodCallProcessor), FieldAttributes.Private | FieldAttributes.InitOnly); var scopeField = typeBuilder.DefineField("scope", typeof(string), FieldAttributes.Private | FieldAttributes.InitOnly); var timeoutSettingsField = typeBuilder.DefineField("timeoutSettings", typeof(TimeoutSettings), FieldAttributes.Private | FieldAttributes.InitOnly); #endregion #region Begin Emit Constructor var constructorBuilder = typeBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, ConstructorParameterTypes); var baseConstructor = typeof(object).GetConstructor(Type.EmptyTypes); var cil = constructorBuilder.GetILGenerator(); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Call, baseConstructor); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_1); cil.Emit(OpCodes.Stfld, processorField); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_2); cil.Emit(OpCodes.Stfld, scopeField); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_3); cil.Emit(OpCodes.Stfld, timeoutSettingsField); #endregion foreach (var subserviceDesc in serviceDescription.Subservices) { #region Emit Subservice Property var proxyClass = CreateProxyClass(rootType, subserviceDesc.Service.Type, path + "/" + subserviceDesc.Name); var fieldBuilder = typeBuilder.DefineField("_" + subserviceDesc.Name, proxyClass, FieldAttributes.Private | FieldAttributes.InitOnly); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_1); cil.Emit(OpCodes.Ldarg_2); cil.Emit(OpCodes.Ldarg_3); cil.Emit(OpCodes.Newobj, proxyClass.GetConstructor(ConstructorParameterTypes)); cil.Emit(OpCodes.Stfld, fieldBuilder); var methodBuilder = typeBuilder.DefineMethod("get_" + subserviceDesc.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual, subserviceDesc.Service.Type, Type.EmptyTypes); methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed); var il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, fieldBuilder); il.Emit(OpCodes.Ret); var propertyBuilder = typeBuilder.DefineProperty(subserviceDesc.Name, PropertyAttributes.None, subserviceDesc.Service.Type, Type.EmptyTypes); propertyBuilder.SetGetMethod(methodBuilder); #endregion } #region End Emit Constructor cil.Emit(OpCodes.Ret); #endregion foreach (var methodDesc in serviceDescription.Methods) { #region Emit Method var parameterTypes = methodDesc.Parameters.Select(x => x.Way == MethodParameterWay.Val ? x.Type : x.Type.MakeByRefType()).ToArray(); var dynamicMethod = EmitDynamicMethod(rootType, path, methodDesc, parameterTypes, codecContainer); dynamicMethods.Add(dynamicMethod); var dynamicMethodPointer = MethodHelpers.ExtractDynamicMethodPointer(dynamicMethod); var methodBuilder = typeBuilder.DefineMethod(methodDesc.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, dynamicMethod.ReturnType, parameterTypes); methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed); var il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, processorField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, scopeField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, timeoutSettingsField); for (int i = 0; i < methodDesc.Parameters.Count; i++) { il.Emit(OpCodes.Ldarg, i + 1); } il.Emit_Ldc_IntPtr(dynamicMethodPointer); il.EmitCalli(OpCodes.Calli, CallingConventions.Standard, dynamicMethod.ReturnType, dynamicMethod.GetParameters().Select(x => x.ParameterType).ToArray(), null); il.Emit(OpCodes.Ret); #endregion } return(typeBuilder.CreateType()); }