コード例 #1
0
        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);
        }
コード例 #2
0
        /// <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);
        }
コード例 #3
0
        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));
        }
コード例 #4
0
        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);
        }