public static TInterface CreateEmptyProxy <TInterface>(DynamicMethodBinder methodBinder, Type binderType, Type ctorArgType, object ctorArg) where TInterface : class { Type interfaceType = typeof(TInterface); // derive unique key for this dynamic assembly by interface, channel and ctor type names var proxyName = $"{PROXY}_" + interfaceType.FullName + binderType?.FullName + $"_{Guid.NewGuid().ToString("N")}"; // get pooled proxy builder ProxyBuilder proxyBuilder = null; TInterface proxy = null; try { proxyBuilder = _proxies.Request(proxyName, () => CreateSimpleProxyBuilder(proxyName, interfaceType, methodBinder, binderType, ctorArgType)); proxy = CreateEmptyProxy <TInterface>(proxyBuilder, ctorArg); } finally { // return builder to the pool if (null != proxyBuilder) { _proxies.Release(proxyName, proxyBuilder); } } return(proxy); }
/// <summary> /// Bind a generated proxy method to an existing target method /// </summary> /// <param name="binder"></param> /// <param name="proxyMethodInfo"></param> /// <param name="typeBuilder"></param> /// <param name="ldindOpCodeTypeMap"></param> /// <param name="stindOpCodeTypeMap"></param> /// <returns></returns> public static MethodBuilder BindMethod(DynamicMethodBinder binder, MethodInfo proxyMethodInfo, TypeBuilder typeBuilder, Dictionary <Type, OpCode> ldindOpCodeTypeMap, Dictionary <Type, OpCode> stindOpCodeTypeMap) { var paramInfos = proxyMethodInfo.GetParameters(); int nofParams = paramInfos.Length; Type[] parameterTypes = new Type[nofParams]; for (int i = 0; i < nofParams; i++) { parameterTypes[i] = paramInfos[i].ParameterType; } Type returnType = proxyMethodInfo.ReturnType; var methodBuilder = typeBuilder.DefineMethod(proxyMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, returnType, parameterTypes); var mIL = methodBuilder.GetILGenerator(); // TODO: Inject call to binder var binderType = binder.GetType(); var binderInvokeInfo = binderType.GetMethod(DynamicMethodBinder.InvokeMethodName, BindingFlags.Instance | BindingFlags.Public); GenerateILBinding(binderInvokeInfo, proxyMethodInfo, mIL, parameterTypes, returnType, ldindOpCodeTypeMap, stindOpCodeTypeMap); return(methodBuilder); }
internal static TInterface BuildEmpty <TInterface>(DynamicMethodBinder binder) where TInterface : class { var paramType = binder.GetType().GetTypeInfo().GetConstructors().First().GetParameters().First().ParameterType; return(ProxyFactory.CreateEmptyProxy <TInterface>(binder, binder.GetType(), paramType, binder.Target)); }
private static ProxyBuilder CreateSimpleProxyBuilder(string proxyName, Type interfaceType, DynamicMethodBinder methodBinder, Type parentType, Type ctorArgType = null) { // create a new assembly for the proxy var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(PROXY_ASSEMBLY), AssemblyBuilderAccess.Run); // create a new module for the proxy var moduleBuilder = assemblyBuilder.DefineDynamicModule(PROXY_MODULE); // Set the class to be public and sealed TypeAttributes typeAttributes = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed; // Construct the type builder TypeBuilder typeBuilder; var genTypeName = $"{PROXY}_" + interfaceType.FullName + parentType?.FullName + $"_{Guid.NewGuid().ToString("N")}_{PROXY}"; if (parentType != null) { typeBuilder = moduleBuilder.DefineType(genTypeName, typeAttributes, parentType); } else { typeBuilder = moduleBuilder.DefineType(genTypeName, typeAttributes); } var allInterfaces = new List <Type>(interfaceType.GetInterfaces()); allInterfaces.Add(interfaceType); // add the interface typeBuilder.AddInterfaceImplementation(interfaceType); // construct the constructor // TODO Type[] ctorArgTypes = { ctorArgType }; CreateParameterizedConstructor(parentType, typeBuilder, ctorArgTypes); // construct the type maps var ldindOpCodeTypeMap = new Dictionary <Type, OpCode>(); ldindOpCodeTypeMap.Add(typeof(Boolean), OpCodes.Ldind_I1); ldindOpCodeTypeMap.Add(typeof(Byte), OpCodes.Ldind_U1); ldindOpCodeTypeMap.Add(typeof(SByte), OpCodes.Ldind_I1); ldindOpCodeTypeMap.Add(typeof(Int16), OpCodes.Ldind_I2); ldindOpCodeTypeMap.Add(typeof(UInt16), OpCodes.Ldind_U2); ldindOpCodeTypeMap.Add(typeof(Int32), OpCodes.Ldind_I4); ldindOpCodeTypeMap.Add(typeof(UInt32), OpCodes.Ldind_U4); ldindOpCodeTypeMap.Add(typeof(Int64), OpCodes.Ldind_I8); ldindOpCodeTypeMap.Add(typeof(UInt64), OpCodes.Ldind_I8); ldindOpCodeTypeMap.Add(typeof(Char), OpCodes.Ldind_U2); ldindOpCodeTypeMap.Add(typeof(Double), OpCodes.Ldind_R8); ldindOpCodeTypeMap.Add(typeof(Single), OpCodes.Ldind_R4); var stindOpCodeTypeMap = new Dictionary <Type, OpCode>(); stindOpCodeTypeMap.Add(typeof(Boolean), OpCodes.Stind_I1); stindOpCodeTypeMap.Add(typeof(Byte), OpCodes.Stind_I1); stindOpCodeTypeMap.Add(typeof(SByte), OpCodes.Stind_I1); stindOpCodeTypeMap.Add(typeof(Int16), OpCodes.Stind_I2); stindOpCodeTypeMap.Add(typeof(UInt16), OpCodes.Stind_I2); stindOpCodeTypeMap.Add(typeof(Int32), OpCodes.Stind_I4); stindOpCodeTypeMap.Add(typeof(UInt32), OpCodes.Stind_I4); stindOpCodeTypeMap.Add(typeof(Int64), OpCodes.Stind_I8); stindOpCodeTypeMap.Add(typeof(UInt64), OpCodes.Stind_I8); stindOpCodeTypeMap.Add(typeof(Char), OpCodes.Stind_I2); stindOpCodeTypeMap.Add(typeof(Double), OpCodes.Stind_R8); stindOpCodeTypeMap.Add(typeof(Single), OpCodes.Stind_R4); // TODO: Allow passing in a binder to handle method calls // construct the method builders from the method infos defined in the interface var methods = GetAllMethods(allInterfaces); foreach (MethodInfo methodInfo in methods) { var methodBuilder = BindMethod(methodBinder, methodInfo, typeBuilder, ldindOpCodeTypeMap, stindOpCodeTypeMap); typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); } // create proxy builder var result = new ProxyBuilder { ProxyName = proxyName, InterfaceType = interfaceType, CtorType = ctorArgType, AssemblyBuilder = assemblyBuilder, ModuleBuilder = moduleBuilder, TypeBuilder = typeBuilder }; return(result); }