Exemplo n.º 1
0
        // The caller sends in an AppDomain type.
        public static void CreateMyAsm(AppDomain curAppDomain)
        {
            // Establish general assembly characteristics.
            AssemblyName assemblyName = new AssemblyName();

            assemblyName.Name    = "MyAssembly";
            assemblyName.Version = new Version("1.0.0.0");
            // Create new assembly within the current AppDomain.
            // AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
            AssemblyBuilder assembly = curAppDomain.DefineDynamicAssembly(assemblyName,
                                                                          AssemblyBuilderAccess.Save);

            // Given that we are building a single-file
            // assembly, the name of the module is the same as the assembly.
            ModuleBuilder module = assembly.DefineDynamicModule("MyAssembly", "MyAssembly.dll");

            // Define a public class named "HelloWorld".
            TypeBuilder helloWorldClass = module.DefineType("MyAssembly.HelloWorld",
                                                            TypeAttributes.Public);

            // Define a private String member variable named "theMessage".
            FieldBuilder msgField = helloWorldClass.DefineField("theMessage",
                                                                Type.GetType("System.String"), FieldAttributes.Private);

            // Create the custom ctor.
            Type[] constructorArgs = new Type[1];
            constructorArgs[0] = typeof(string);
            ConstructorBuilder constructor = helloWorldClass.DefineConstructor(MethodAttributes.Public,
                                                                               CallingConventions.Standard, constructorArgs);

            ILGenerator constructorIL = constructor.GetILGenerator();

            constructorIL.Emit(OpCodes.Ldarg_0);

            Type            objectClass      = typeof(object);
            ConstructorInfo superConstructor = objectClass.GetConstructor(new Type[0]);

            constructorIL.Emit(OpCodes.Call, superConstructor);
            constructorIL.Emit(OpCodes.Ldarg_0);
            constructorIL.Emit(OpCodes.Ldarg_1);
            constructorIL.Emit(OpCodes.Stfld, msgField);
            constructorIL.Emit(OpCodes.Ret);

            // Create the default ctor.
            helloWorldClass.DefineDefaultConstructor(MethodAttributes.Public);

            // Now create the GetMsg() method.
            MethodBuilder getMsgMethod = helloWorldClass.DefineMethod("GetMsg",
                                                                      MethodAttributes.Public, typeof(string), null);

            ILGenerator methodIL = getMsgMethod.GetILGenerator();

            methodIL.Emit(OpCodes.Ldarg_0);
            methodIL.Emit(OpCodes.Ldfld, msgField);
            methodIL.Emit(OpCodes.Ret);

            // Create the SayHello method.
            MethodBuilder sayHiMethod = helloWorldClass.DefineMethod("SayHello",
                                                                     MethodAttributes.Public, null, null);

            methodIL = sayHiMethod.GetILGenerator();
            methodIL.EmitWriteLine("Hello from the HelloWorld class!");
            methodIL.Emit(OpCodes.Ret);

            // "Bake" the class HelloWorld.
            // (Baking is the formal term for emitting the type.)
            helloWorldClass.CreateType();
            // (Optionally) save the assembly to file.
            assembly.Save("MyAssembly.dll");
        }
        public Type EmitProxyType(string entityTypeName, IDictionary <string, Type> entityFieldDic)
        {
            string      typeName    = string.Format("{0}.{1}", this.assemblyName, entityTypeName);
            TypeBuilder typeBuilder = this.moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable);
            //typeBuilder.AddInterfaceImplementation(interfaceType);

            List <FieldBuilder> fieldBuilderList = new List <FieldBuilder>();

            foreach (string propertyName in entityFieldDic.Keys)
            {
                #region 定义属性
                Type         propertyType = entityFieldDic[propertyName];
                FieldBuilder fieldBuilder = typeBuilder.DefineField("m_" + propertyName, propertyType, FieldAttributes.Private);
                fieldBuilderList.Add(fieldBuilder);
                fieldBuilder.SetConstant(TypeHelper.ChangeType(propertyType, TypeHelper.GetDefaultValue(propertyType)));
                PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null);

                //定义属性的get方法
                MethodBuilder getPropertyBuilder = typeBuilder.DefineMethod("get", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
                                                                            propertyType, Type.EmptyTypes);

                ILGenerator getAIL = getPropertyBuilder.GetILGenerator();
                getAIL.Emit(OpCodes.Ldarg_0);
                getAIL.Emit(OpCodes.Ldfld, fieldBuilder);
                getAIL.Emit(OpCodes.Ret);

                //定义属性A的set方法
                MethodBuilder setPropertyABuilder = typeBuilder.DefineMethod("set", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
                                                                             null, new Type[] { propertyType });
                ILGenerator setAIL = setPropertyABuilder.GetILGenerator();
                setAIL.Emit(OpCodes.Ldarg_0);
                setAIL.Emit(OpCodes.Ldarg_1);
                setAIL.Emit(OpCodes.Stfld, fieldBuilder);
                setAIL.Emit(OpCodes.Ret);

                propertyBuilder.SetGetMethod(getPropertyBuilder);
                propertyBuilder.SetSetMethod(setPropertyABuilder);
                #endregion
            }

            #region Emit Ctor
            ConstructorBuilder ctor    = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
            ILGenerator        ctorGen = ctor.GetILGenerator();
            ctorGen.Emit(OpCodes.Ldarg_0);
            ctorGen.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[] { }));

            foreach (FieldBuilder fieldBuilder in fieldBuilderList)
            {
                if (fieldBuilder.FieldType == typeof(string))
                {
                    ctorGen.Emit(OpCodes.Ldarg_0);
                    ctorGen.Emit(OpCodes.Ldstr, "");
                    ctorGen.Emit(OpCodes.Stfld, fieldBuilder);
                }
            }

            ctorGen.Emit(OpCodes.Ret);
            #endregion

            Type target = typeBuilder.CreateType();
            return(target);
        }
Exemplo n.º 3
0
        static void DefineCtors(TypeBuilder proxyTB,
                                Type superClass,
                                string initName,
                                string postInitName,
                                ISeq ctors,
                                ISeq ctorTypes,
                                FieldBuilder initFB,
                                FieldBuilder postInitFB,
                                FieldBuilder stateFB,
                                string factoryName)
        {
            ISeq s1 = ctors;

            for (ISeq s = ctorTypes; s != null; s = s.next())
            {
                // TODO: Get rid of this mess by making sure the metadata on the keys of the constructors map gets copied to the constructor-types map.  Sigh.
                IPersistentMap ctorAttributes = GenInterface.ExtractAttributes(RT.meta(((IMapEntry)s1.first()).key()));
                s1 = s1.next();

                IMapEntry me = (IMapEntry)s.first();
                ISeq      thisParamTypesV = (ISeq)me.key();
                ISeq      baseParamTypesV = (ISeq)me.val();

                Type[] thisParamTypes = CreateTypeArray(thisParamTypesV);
                Type[] baseParamTypes = CreateTypeArray(baseParamTypesV);

                BindingFlags    flags     = BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
                ConstructorInfo superCtor = superClass.GetConstructor(flags, null, baseParamTypes, null);

                if (superCtor == null || superCtor.IsPrivate)
                {
                    throw new InvalidOperationException("Base class constructor missing or private");
                }

                ConstructorBuilder cb = proxyTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, thisParamTypes);
                GenInterface.SetCustomAttributes(cb, ctorAttributes);

                CljILGen gen = new CljILGen(cb.GetILGenerator());

                Label noInitLabel      = gen.DefineLabel();
                Label noPostInitLabel  = gen.DefineLabel();
                Label endPostInitLabel = gen.DefineLabel();
                Label endLabel         = gen.DefineLabel();

                LocalBuilder locSuperArgs = gen.DeclareLocal(typeof(object));
                LocalBuilder locInitVal   = gen.DeclareLocal(typeof(object));

                if (initFB != null)
                {
                    // init supplied
                    EmitGetVar(gen, initFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                     // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                        {
                            gen.Emit(OpCodes.Box, thisParamTypes[i]);
                        }
                    }

                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length]);

                    // Expecting:  [[super-ctor-args...] state]

                    // store the init return in a local
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Stloc, locInitVal);

                    // store the first element in a local
                    gen.EmitInt(0);                             // gen.Emit(OpCodes.Ldc_I4_0);
                    gen.EmitCall(Method_RT_nth);                // gen.Emit(OpCodes.Call, Method_RT_nth);
                    gen.Emit(OpCodes.Stloc, locSuperArgs);

                    // Stack this + super-ctor-args + call base-class ctor.
                    gen.EmitLoadArg(0);                         // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < baseParamTypes.Length; i++)
                    {
                        gen.Emit(OpCodes.Ldloc, locSuperArgs);
                        gen.EmitInt(i);                         // gen.Emit(OpCodes.Ldc_I4, i);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        if (baseParamTypes[i].IsValueType)
                        {
                            gen.Emit(OpCodes.Unbox_Any, baseParamTypes[i]);
                        }
                        else
                        {
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                        }
                    }

                    gen.Emit(OpCodes.Call, superCtor);

                    if (stateFB != null)
                    {
                        gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
                        gen.Emit(OpCodes.Ldloc, locInitVal);
                        gen.EmitInt(1);                         // gen.Emit(OpCodes.Ldc_I4_1);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        gen.Emit(OpCodes.Castclass, typeof(object));
                        gen.EmitFieldSet(stateFB);              // gen.Emit(OpCodes.Stfld, stateFB);
                    }

                    gen.Emit(OpCodes.Br_S, endLabel);

                    // No init found
                    gen.MarkLabel(noInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen, initName);

                    gen.MarkLabel(endLabel);
                }
                else  // no InitFB supplied.
                {
                    bool ok = thisParamTypes.Length == baseParamTypes.Length;
                    for (int i = 0; ok && i < thisParamTypes.Length; i++)
                    {
                        ok = baseParamTypes[i].IsAssignableFrom(thisParamTypes[i]);
                    }
                    if (!ok)
                    {
                        throw new InvalidOperationException(":init not specified, but ctor and super ctor args differ");
                    }
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (baseParamTypes[i] != thisParamTypes[i])
                        {
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                        }
                    }
                    gen.Emit(OpCodes.Call, superCtor);
                }

                if (postInitFB != null)
                {
                    // post-init supplied
                    EmitGetVar(gen, postInitFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noPostInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                        {
                            gen.Emit(OpCodes.Box, thisParamTypes[i]);
                        }
                        gen.Emit(OpCodes.Castclass, thisParamTypes[i]);
                    }
                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);
                    gen.Emit(OpCodes.Pop);
                    gen.Emit(OpCodes.Br_S, endPostInitLabel);

                    // no post-init found

                    gen.MarkLabel(noPostInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen, postInitName + " not defined");

                    gen.MarkLabel(endPostInitLabel);
                }

                gen.Emit(OpCodes.Ret);


                if (!String.IsNullOrEmpty(factoryName))
                {
                    MethodBuilder factoryMB = proxyTB.DefineMethod(factoryName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, proxyTB, thisParamTypes);
                    CljILGen      genf      = new CljILGen(factoryMB.GetILGenerator());

                    LocalBuilder[] locals = new LocalBuilder[thisParamTypes.Length];
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        locals[i] = genf.DeclareLocal(thisParamTypes[i]);
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);
                        genf.Emit(OpCodes.Stloc, locals[i]);
                    }


                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);
                    }
                    genf.EmitNew(cb);                           // genf.Emit(OpCodes.Newobj, cb);
                    genf.Emit(OpCodes.Ret);
                }
            }
        }
        internal static IEnumerable ToDataSource(this IEnumerable <Graphic> graphics,
                                                 Dictionary <string, Type> fieldInfo,
                                                 Dictionary <string, object[]> rangeDomainInfo,
                                                 Dictionary <string, Field> fieldProps,
                                                 string uniqueID,
                                                 IEnumerable <Graphic> filterGraphics,
                                                 out Type objectType)
        {
            objectType = null;
            IDictionary firstDict = null;
            IEnumerable <IDictionary <string, object> > list = GetGraphicsEnumerable(graphics);

            if (fieldInfo == null)
            {
                if (list != null)
                {
                    IEnumerator enumList = list.GetEnumerator();
                    if (enumList != null && enumList.MoveNext())
                    {
                        firstDict = enumList.Current as IDictionary;
                        if (firstDict != null)
                        {
                            while (enumList.MoveNext())
                            {
                                IDictionary nextDict = enumList.Current as IDictionary;
                                foreach (DictionaryEntry pair in nextDict)
                                {
                                    Type t = GetValueType(pair.Key as string, pair.Value, fieldInfo);
                                    if (!firstDict.Contains(pair.Key))                                          // Attribute doesn't exist => add it
                                    {
                                        object defaultValue = t.IsValueType ? Activator.CreateInstance(t) : null;
                                        firstDict.Add(pair.Key, defaultValue);
                                    }
                                    else                                       // Attribute exists => check for data type compatibility
                                    {
                                        Type typeInFirstDict = GetValueType(pair.Key as string, firstDict[pair.Key], fieldInfo);
                                        if (typeInFirstDict != typeof(object) &&                                // object type in firstDict covers all data types
                                            pair.Value != null &&                                               // null values in nextDict match the nullable data type associated with the attribute in firstDict
                                            !t.IsOfType(typeInFirstDict))                                       // attribute data types don't match
                                        {
                                            throw new InvalidCastException(string.Format(Properties.Resources.FeatureDataGrid_MixedAttributeTypesNotAllowed,
                                                                                         firstDict[pair.Key].GetType(), pair.Key));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (firstDict == null && fieldInfo == null)
            {
                return new object[] { }
            }
            ;

            string typeSignature = GetTypeSignature(firstDict, fieldInfo);
            Dictionary <string, Type> properties = new Dictionary <string, Type>();

            _fieldMapping = new Dictionary <string, string>();
            if (fieldInfo != null)  // FeatureLayer
            {
                foreach (string key in fieldInfo.Keys)
                {
                    string keyToUse = GetMappedKey(key);
                    Type   t        = fieldInfo[key];
                    properties.Add(keyToUse, t);
                }
            }
            else                    // GraphicsLayer
            {
                foreach (DictionaryEntry pair in firstDict)
                {
                    string keyToUse = GetMappedKey(pair.Key.ToString());
                    Type   t        = GetValueType(keyToUse, pair.Value, fieldInfo);
                    properties.Add(keyToUse, t);
                }
            }
            objectType = GetTypeByTypeSignature(typeSignature);

            if (objectType == null)
            {
                TypeBuilder tb = GetTypeBuilder(typeSignature);

                FieldBuilder       fieldBuilder       = tb.DefineField("_graphicSibling", typeof(Graphic), FieldAttributes.Private);
                ConstructorBuilder constructorBuilder = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(Graphic) });
                ILGenerator        cbIL = constructorBuilder.GetILGenerator();
                cbIL.Emit(OpCodes.Ldarg_0);
                cbIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
                cbIL.Emit(OpCodes.Ldarg_0);
                cbIL.Emit(OpCodes.Ldarg_1);
                cbIL.Emit(OpCodes.Stfld, fieldBuilder);
                cbIL.Emit(OpCodes.Ret);

                MethodBuilder methodBuilder = tb.DefineMethod("GetGraphicSibling", MethodAttributes.Public, typeof(Graphic), Type.EmptyTypes);
                ILGenerator   mbIL          = methodBuilder.GetILGenerator();
                mbIL.Emit(OpCodes.Ldarg_0);
                mbIL.Emit(OpCodes.Ldfld, fieldBuilder);
                mbIL.Emit(OpCodes.Ret);

                int order = 0;
                foreach (string key in properties.Keys)
                {
                    if (fieldProps != null) // FeatureLayer
                    {
                        if (_fieldMapping.KeyOfValue(key) != null)
                        {
                            string mappedKey = _fieldMapping.KeyOfValue(key);
                            if (fieldProps.ContainsKey(mappedKey))    // Only create the property if the key is contained in field properties
                            {
                                Field fld = fieldProps[mappedKey];
                                if (IsViewableAttribute(fld))
                                {
                                    CreateProperty(tb, key, properties[key], rangeDomainInfo, fld, order++, uniqueID == key);
                                }
                            }
                        }
                    }
                    else    // GraphicsLayer
                    {
                        CreateProperty(tb, key, properties[key], rangeDomainInfo, null, order++, uniqueID == key);
                    }
                }

                objectType = tb.CreateType();

                _typeBySignature.Add(typeSignature, objectType);
            }
            return(GenerateEnumerable(objectType, graphics, properties.Keys.ToArray(), filterGraphics));
        }
Exemplo n.º 5
0
        /// <summary>
        /// 动态生成接口的实现类
        /// </summary>
        /// <param name="interfaceType"></param>
        /// <param name="constructor"></param>
        /// <returns></returns>
        private Type BuildTargetType(Type interfaceType, params object[] constructor)
        {
            targetType = interfaceType;
            string assemblyName = targetType.Name + "ProxyAssembly";
            string moduleName   = targetType.Name + "ProxyModule";
            string typeName     = targetType.Name + "Proxy";

            AssemblyName    assyName    = new AssemblyName(assemblyName);
            AssemblyBuilder assyBuilder = AssemblyBuilder.DefineDynamicAssembly(assyName, AssemblyBuilderAccess.Run);
            ModuleBuilder   modBuilder  = assyBuilder.DefineDynamicModule(moduleName);

            //新类型的属性
            TypeAttributes newTypeAttribute = TypeAttributes.Class | TypeAttributes.Public;
            //父类型
            Type parentType;

            //要实现的接口
            Type[] interfaceTypes;

            if (targetType.IsInterface)
            {
                parentType     = typeof(object);
                interfaceTypes = new Type[] { targetType };
            }
            else
            {
                parentType     = targetType;
                interfaceTypes = Type.EmptyTypes;
            }
            //得到类型生成器
            TypeBuilder typeBuilder = modBuilder.DefineType(typeName, newTypeAttribute, parentType, interfaceTypes);

            //定义一个字段存放httpService
            var          httpType         = typeof(HttpService);
            FieldBuilder httpServiceField = typeBuilder.DefineField("httpService",
                                                                    httpType, FieldAttributes.Public);

            //定义一个字段存放IServiceProvider
            var          iServiceProviderType = typeof(IServiceProvider);
            FieldBuilder serviceProviderField = typeBuilder.DefineField("iServiceProvider",
                                                                        iServiceProviderType, FieldAttributes.Public);

            //定义一个集合存放参数集合
            FieldBuilder paramterArrField = typeBuilder.DefineField("paramterArr",
                                                                    typeof(List <object>), FieldAttributes.Public);
            //创建构造函数
            ConstructorBuilder constructorBuilder =
                typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { httpType, iServiceProviderType });

            //il创建构造函数,对httpService和IServiceProvider两个字段进行赋值,同时初始化存放参数的集合
            ILGenerator ilgCtor = constructorBuilder.GetILGenerator();

            ilgCtor.Emit(OpCodes.Ldarg_0); //加载当前类
            ilgCtor.Emit(OpCodes.Ldarg_1);
            ilgCtor.Emit(OpCodes.Stfld, httpServiceField);

            ilgCtor.Emit(OpCodes.Ldarg_0); //加载当前类
            ilgCtor.Emit(OpCodes.Ldarg_2);
            ilgCtor.Emit(OpCodes.Stfld, serviceProviderField);

            ilgCtor.Emit(OpCodes.Ldarg_0); //加载当前类
            ilgCtor.Emit(OpCodes.Newobj, typeof(List <object>).GetConstructors().First());
            ilgCtor.Emit(OpCodes.Stfld, paramterArrField);
            ilgCtor.Emit(OpCodes.Ret); //返回

            MethodInfo[] targetMethods = targetType.GetMethods();

            foreach (MethodInfo targetMethod in targetMethods)
            {
                //只挑出virtual的方法
                if (targetMethod.IsVirtual)
                {
                    //缓存接口的方法体,便于后续将方法体传递给httpService
                    string methodKey = Guid.NewGuid().ToString();
                    MethodsCache[methodKey] = targetMethod;

                    //得到方法的各个参数的类型和参数
                    var paramInfo     = targetMethod.GetParameters();
                    var parameterType = paramInfo.Select(it => it.ParameterType).ToArray();
                    var returnType    = targetMethod.ReturnType;
                    //方法返回值只能是task,即只支持异步,因为http操作是io操作
                    if (!typeof(Task).IsAssignableFrom(returnType))
                    {
                        throw new Exception("return type must be task<>");
                    }
                    var underType = returnType.IsGenericType ? returnType.GetGenericArguments().First() : returnType;

                    //通过emit生成方法体
                    MethodBuilder methodBuilder = typeBuilder.DefineMethod(targetMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, targetMethod.ReturnType, parameterType);
                    ILGenerator   ilGen         = methodBuilder.GetILGenerator();

                    MethodInfo executeMethod = null;
                    var        methodTmp     = httpType.GetMethod("ExecuteAsync");

                    if (methodTmp == null)
                    {
                        throw new Exception("找不到执行方法");
                    }
                    executeMethod = methodTmp.IsGenericMethod ? methodTmp.MakeGenericMethod(underType) : methodTmp;

                    // 栈底放这玩意,加载字段前要加载类实例,即Ldarg_0
                    ilGen.Emit(OpCodes.Ldarg_0);
                    ilGen.Emit(OpCodes.Ldfld, httpServiceField);

                    //把所有参数都放到list<object>里
                    ilGen.Emit(OpCodes.Ldarg_0);
                    ilGen.Emit(OpCodes.Ldfld, paramterArrField);
                    for (int i = 0; i < parameterType.Length; i++)
                    {
                        ilGen.Emit(OpCodes.Dup);
                        ilGen.Emit(OpCodes.Ldarg_S, i + 1);
                        if (parameterType[i].IsValueType)
                        {
                            ilGen.Emit(OpCodes.Box, parameterType[i]);
                        }
                        ilGen.Emit(OpCodes.Callvirt, typeof(List <object>).GetMethod("Add"));
                    }

                    // 当前栈[httpServiceField paramterArrField]
                    //从缓存里取出方法体
                    ilGen.Emit(OpCodes.Call,
                               typeof(FeignProxyBuilder).GetMethod("get_MethodsCache", BindingFlags.Static | BindingFlags.Public));
                    ilGen.Emit(OpCodes.Ldstr, methodKey);
                    ilGen.Emit(OpCodes.Call, typeof(Dictionary <string, MethodInfo>).GetMethod("get_Item"));

                    ilGen.Emit(OpCodes.Ldarg_0);
                    ilGen.Emit(OpCodes.Ldfld, serviceProviderField);

                    ilGen.Emit(OpCodes.Callvirt, executeMethod);
                    //清空list里的参数
                    ilGen.Emit(OpCodes.Ldarg_0);
                    ilGen.Emit(OpCodes.Ldfld, paramterArrField);
                    ilGen.Emit(OpCodes.Callvirt, typeof(List <object>).GetMethod("Clear"));
                    // pop the stack if return void
                    if (targetMethod.ReturnType == typeof(void))
                    {
                        ilGen.Emit(OpCodes.Pop);
                    }

                    // complete
                    ilGen.Emit(OpCodes.Ret);
                    typeBuilder.DefineMethodOverride(methodBuilder, targetMethod);
                }
            }

            var resultType = typeBuilder.CreateTypeInfo().AsType();

            return(resultType);
        }
Exemplo n.º 6
0
        private static bool TryCreatePropertyDescriptor(ref PropertyDescriptor descriptor)
        {
            try
            {
                PropertyInfo property = descriptor.ComponentType.GetProperty(descriptor.Name);
                if (property == null)
                {
                    return(false);
                }

                lock (properties)
                {
                    PropertyDescriptor foundBuiltAlready;
                    if (properties.TryGetValue(property, out foundBuiltAlready))
                    {
                        descriptor = foundBuiltAlready;
                        return(true);
                    }

                    string      name = "_c" + Interlocked.Increment(ref counter).ToString();
                    TypeBuilder tb   = moduleBuilder.DefineType(name,
                                                                TypeAttributes.Sealed | TypeAttributes.NotPublic | TypeAttributes.Class |
                                                                TypeAttributes.BeforeFieldInit | TypeAttributes.AutoClass | TypeAttributes.Public,
                                                                typeof(ChainingPropertyDescriptor));

                    // ctor calls base
                    ConstructorBuilder cb =
                        tb.DefineConstructor(
                            MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName |
                            MethodAttributes.RTSpecialName, CallingConventions.Standard,
                            new Type[] { typeof(PropertyDescriptor) });
                    ILGenerator il = cb.GetILGenerator();
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Call,
                            typeof(ChainingPropertyDescriptor).GetConstructor(
                                BindingFlags.NonPublic | BindingFlags.Instance, null,
                                new Type[] { typeof(PropertyDescriptor) }, null));
                    il.Emit(OpCodes.Ret);

                    MethodBuilder mb;
                    MethodInfo    baseMethod;
                    if (property.CanRead)
                    {
                        // obtain the implementation that we want to override
                        baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("GetValue");
                        // create a new method that accepts an object and returns an object (as per the base)
                        mb = tb.DefineMethod(baseMethod.Name,
                                             MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
                                             MethodAttributes.Final,
                                             baseMethod.CallingConvention, baseMethod.ReturnType, new Type[] { typeof(object) });
                        // start writing IL into the method
                        il = mb.GetILGenerator();
                        if (property.DeclaringType.IsValueType)
                        {
                            // upbox the object argument into our known (instance) struct type
                            LocalBuilder lb = il.DeclareLocal(property.DeclaringType);
                            il.Emit(OpCodes.Ldarg_1);
                            il.Emit(OpCodes.Unbox_Any, property.DeclaringType);
                            il.Emit(OpCodes.Stloc_0);
                            il.Emit(OpCodes.Ldloca_S, lb);
                        }
                        else
                        {
                            // cast the object argument into our known class type
                            il.Emit(OpCodes.Ldarg_1);
                            il.Emit(OpCodes.Castclass, property.DeclaringType);
                        }
                        // call the "get" method
                        il.Emit(OpCodes.Callvirt, property.GetGetMethod());

                        if (property.PropertyType.IsValueType)
                        {
                            // box it from the known (value) struct type
                            il.Emit(OpCodes.Box, property.PropertyType);
                        }
                        // return the value
                        il.Emit(OpCodes.Ret);
                        // signal that this method should override the base
                        tb.DefineMethodOverride(mb, baseMethod);
                    }

                    bool supportsChangeEvents = descriptor.SupportsChangeEvents, isReadOnly = descriptor.IsReadOnly;

                    // override SupportsChangeEvents
                    baseMethod = typeof(ChainingPropertyDescriptor).GetProperty("SupportsChangeEvents").GetGetMethod();
                    mb         = tb.DefineMethod(baseMethod.Name,
                                                 MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
                                                 MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
                                                 baseMethod.ReturnType, Type.EmptyTypes);
                    il = mb.GetILGenerator();
                    if (supportsChangeEvents)
                    {
                        il.Emit(OpCodes.Ldc_I4_1);
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldc_I4_0);
                    }
                    il.Emit(OpCodes.Ret);
                    tb.DefineMethodOverride(mb, baseMethod);

                    // override IsReadOnly
                    baseMethod = typeof(ChainingPropertyDescriptor).GetProperty("IsReadOnly").GetGetMethod();
                    mb         = tb.DefineMethod(baseMethod.Name,
                                                 MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
                                                 MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
                                                 baseMethod.ReturnType, Type.EmptyTypes);
                    il = mb.GetILGenerator();
                    if (isReadOnly)
                    {
                        il.Emit(OpCodes.Ldc_I4_1);
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldc_I4_0);
                    }
                    il.Emit(OpCodes.Ret);
                    tb.DefineMethodOverride(mb, baseMethod);

                    // for classes, implement write (would be lost in unbox for structs)

                    if (!property.DeclaringType.IsValueType)
                    {
                        if (!isReadOnly && property.CanWrite)
                        {
                            // override set method
                            baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("SetValue");
                            mb         = tb.DefineMethod(baseMethod.Name,
                                                         MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
                                                         MethodAttributes.Final, baseMethod.CallingConvention, baseMethod.ReturnType,
                                                         new Type[] { typeof(object), typeof(object) });
                            il = mb.GetILGenerator();
                            il.Emit(OpCodes.Ldarg_1);
                            il.Emit(OpCodes.Castclass, property.DeclaringType);
                            il.Emit(OpCodes.Ldarg_2);
                            if (property.PropertyType.IsValueType)
                            {
                                il.Emit(OpCodes.Unbox_Any, property.PropertyType);
                            }
                            else
                            {
                                il.Emit(OpCodes.Castclass, property.PropertyType);
                            }
                            il.Emit(OpCodes.Callvirt, property.GetSetMethod());
                            il.Emit(OpCodes.Ret);
                            tb.DefineMethodOverride(mb, baseMethod);
                        }

                        if (supportsChangeEvents)
                        {
                            EventInfo ei = property.DeclaringType.GetEvent(property.Name + "Changed");
                            if (ei != null)
                            {
                                baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("AddValueChanged");
                                mb         = tb.DefineMethod(baseMethod.Name,
                                                             MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
                                                             MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
                                                             baseMethod.ReturnType, new Type[] { typeof(object), typeof(EventHandler) });
                                il = mb.GetILGenerator();
                                il.Emit(OpCodes.Ldarg_1);
                                il.Emit(OpCodes.Castclass, property.DeclaringType);
                                il.Emit(OpCodes.Ldarg_2);
                                il.Emit(OpCodes.Callvirt, ei.GetAddMethod());
                                il.Emit(OpCodes.Ret);
                                tb.DefineMethodOverride(mb, baseMethod);

                                baseMethod = typeof(ChainingPropertyDescriptor).GetMethod("RemoveValueChanged");
                                mb         = tb.DefineMethod(baseMethod.Name,
                                                             MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
                                                             MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
                                                             baseMethod.ReturnType, new Type[] { typeof(object), typeof(EventHandler) });
                                il = mb.GetILGenerator();
                                il.Emit(OpCodes.Ldarg_1);
                                il.Emit(OpCodes.Castclass, property.DeclaringType);
                                il.Emit(OpCodes.Ldarg_2);
                                il.Emit(OpCodes.Callvirt, ei.GetRemoveMethod());
                                il.Emit(OpCodes.Ret);
                                tb.DefineMethodOverride(mb, baseMethod);
                            }
                        }
                    }

                    PropertyDescriptor newDesc =
                        tb.CreateType()
                        .GetConstructor(new Type[] { typeof(PropertyDescriptor) })
                        .Invoke(new object[] { descriptor }) as PropertyDescriptor;
                    if (newDesc == null)
                    {
                        return(false);
                    }
                    descriptor = newDesc;
                    properties.Add(property, descriptor);
                    return(true);
                }
            }
            catch
            {
                return(false);
            }
        }
Exemplo n.º 7
0
        public CodeGen DefineConstructor(Type[] paramTypes)
        {
            ConstructorBuilder cb = _myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, paramTypes);

            return(CreateCodeGen(cb, cb.GetILGenerator(), paramTypes));
        }
Exemplo n.º 8
0
        public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders)
        {
            TypeBuilder typeBuilder = assembly.DefineType(
                "__sort",
                TypeAttributes.Public,
                typeof(object)
                );

            #region Constructor
            {
                ConstructorBuilder ctor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes
                    );

                ILGenerator il = ctor.GetILGenerator();

                // : base()
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

                // return;
                il.Emit(OpCodes.Ret);
            }
            #endregion

            #region IComparer
            typeBuilder.AddInterfaceImplementation(typeof(IComparer));

            MethodBuilder compareMethod;

            #region Compare
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Compare",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new Type[] { typeof(object), typeof(object) });

                LocalBuilder a = emitter.CreateLocal(objectType);
                LocalBuilder b = emitter.CreateLocal(objectType);

                LocalBuilder v = emitter.CreateLocal(typeof(int));

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(a);

                emitter.LoadArgument(2);
                emitter.CastAs(objectType);
                emitter.StoreLocal(b);

                emitter.Load(0);
                emitter.StoreLocal(v);

                Label end = emitter.CreateLabel();

                for (int i = 0; i < orders.Length; ++i)
                {
                    if (i > 0)
                    {
                        emitter.LoadLocal(v);
                        emitter.BranchIfTrue(end);                           // if ( v != 0 ) return v;
                    }

                    OrderInfo orderInfo = orders[i];

                    Property prop = orderInfo.Property;
                    int      sign = orderInfo.Sign;

                    emitter.LoadLocal(a);
                    emitter.Chain(prop);

                    bool couldCompare =
                        emitter.CompareTo(sign, delegate()
                    {
                        emitter.LoadLocal(b);
                        emitter.Chain(prop);
                    });

                    if (!couldCompare)
                    {
                        throw new InvalidOperationException("Property is not comparable.");
                    }

                    emitter.StoreLocal(v);
                }

                emitter.MarkLabel(end);

                emitter.LoadLocal(v);
                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IComparer).GetMethod(
                        "Compare",
                        new Type[]
                {
                    typeof(object),
                    typeof(object)
                }
                        )
                    );

                compareMethod = emitter.Method;
            }
            #endregion
            #endregion

            Type comparerType = typeBuilder.CreateType();

            return((IComparer)Activator.CreateInstance(comparerType));
        }
Exemplo n.º 9
0
        /// <summary>
        /// The CreateType method creates a new data class with a given set of public properties and returns the System.Type object for the newly created class. If a data class with an identical sequence of properties has already been created, the System.Type object for this class is returned.
        /// Data classes implement private instance variables and read/write property accessors for the specified properties.Data classes also override the Equals and GetHashCode members to implement by-value equality.
        /// Data classes are created in an in-memory assembly in the current application domain. All data classes inherit from <see cref="DynamicClass"/> and are given automatically generated names that should be considered private (the names will be unique within the application domain but not across multiple invocations of the application). Note that once created, a data class stays in memory for the lifetime of the current application domain. There is currently no way to unload a dynamically created data class.
        /// The dynamic expression parser uses the CreateClass methods to generate classes from data object initializers. This feature in turn is often used with the dynamic Select method to create projections.
        /// </summary>
        /// <param name="properties">The DynamicProperties</param>
        /// <param name="createParameterCtor">Create a constructor with parameters. Default set to true. Note that for Linq-to-Database objects, this needs to be set to false.</param>
        /// <returns>Type</returns>
        /// <example>
        /// <code>
        /// <![CDATA[
        /// DynamicProperty[] props = new DynamicProperty[] { new DynamicProperty("Name", typeof(string)), new DynamicProperty("Birthday", typeof(DateTime)) };
        /// Type type = DynamicClassFactory.CreateType(props);
        /// DynamicClass dynamicClass = Activator.CreateInstance(type) as DynamicClass;
        /// dynamicClass.SetDynamicProperty("Name", "Albert");
        /// dynamicClass.SetDynamicProperty("Birthday", new DateTime(1879, 3, 14));
        /// Console.WriteLine(dynamicClass);
        /// ]]>
        /// </code>
        /// </example>
        public static Type CreateType([NotNull] IList <DynamicProperty> properties, bool createParameterCtor = true)
        {
            Check.HasNoNulls(properties, nameof(properties));

            Type[]   types = properties.Select(p => p.Type).ToArray();
            string[] names = properties.Select(p => p.Name).ToArray();

            string key = GenerateKey(properties, createParameterCtor);

            Type type;

            if (!GeneratedTypes.TryGetValue(key, out type))
            {
                // We create only a single class at a time, through this lock
                // Note that this is a variant of the double-checked locking.
                // It is safe because we are using a thread safe class.
                lock (GeneratedTypes)
                {
                    if (!GeneratedTypes.TryGetValue(key, out type))
                    {
                        int index = Interlocked.Increment(ref _index);

                        string name = names.Length != 0 ? $"<>f__AnonymousType{index}`{names.Length}" : $"<>f__AnonymousType{index}";

                        TypeBuilder tb = ModuleBuilder.DefineType(name, TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, typeof(DynamicClass));
                        tb.SetCustomAttribute(CompilerGeneratedAttributeBuilder);

                        GenericTypeParameterBuilder[] generics;

                        if (names.Length != 0)
                        {
                            string[] genericNames = names.Select(genericName => $"<{genericName}>j__TPar").ToArray();
                            generics = tb.DefineGenericParameters(genericNames);
                            foreach (GenericTypeParameterBuilder b in generics)
                            {
                                b.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
                            }
                        }
                        else
                        {
                            generics = new GenericTypeParameterBuilder[0];
                        }

                        var fields = new FieldBuilder[names.Length];

                        // There are two for cycles because we want to have all the getter methods before all the other methods
                        for (int i = 0; i < names.Length; i++)
                        {
                            // field
                            fields[i] = tb.DefineField($"<{names[i]}>i__Field", generics[i].AsType(), FieldAttributes.Private | FieldAttributes.InitOnly);
                            fields[i].SetCustomAttribute(DebuggerBrowsableAttributeBuilder);

                            PropertyBuilder property = tb.DefineProperty(names[i], PropertyAttributes.None, CallingConventions.HasThis, generics[i].AsType(), EmptyTypes);

                            // getter
                            MethodBuilder getter = tb.DefineMethod($"get_{names[i]}", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, generics[i].AsType(), null);
                            getter.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
                            ILGenerator ilgeneratorGetter = getter.GetILGenerator();
                            ilgeneratorGetter.Emit(OpCodes.Ldarg_0);
                            ilgeneratorGetter.Emit(OpCodes.Ldfld, fields[i]);
                            ilgeneratorGetter.Emit(OpCodes.Ret);
                            property.SetGetMethod(getter);

                            // setter
                            MethodBuilder setter = tb.DefineMethod($"set_{names[i]}", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, null, new[] { generics[i].AsType() });
                            setter.SetCustomAttribute(CompilerGeneratedAttributeBuilder);

                            // workaround for https://github.com/dotnet/corefx/issues/7792
                            setter.DefineParameter(1, ParameterAttributes.In, generics[i].Name);

                            ILGenerator ilgeneratorSetter = setter.GetILGenerator();
                            ilgeneratorSetter.Emit(OpCodes.Ldarg_0);
                            ilgeneratorSetter.Emit(OpCodes.Ldarg_1);
                            ilgeneratorSetter.Emit(OpCodes.Stfld, fields[i]);
                            ilgeneratorSetter.Emit(OpCodes.Ret);
                            property.SetSetMethod(setter);
                        }

                        // ToString()
                        MethodBuilder toString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(string), EmptyTypes);
                        toString.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
                        ILGenerator ilgeneratorToString = toString.GetILGenerator();
                        ilgeneratorToString.DeclareLocal(typeof(StringBuilder));
                        ilgeneratorToString.Emit(OpCodes.Newobj, StringBuilderCtor);
                        ilgeneratorToString.Emit(OpCodes.Stloc_0);

                        // Equals
                        MethodBuilder equals = tb.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(bool), new[] { typeof(object) });
                        equals.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
                        equals.DefineParameter(1, ParameterAttributes.In, "value");

                        ILGenerator ilgeneratorEquals = equals.GetILGenerator();
                        ilgeneratorEquals.DeclareLocal(tb.AsType());
                        ilgeneratorEquals.Emit(OpCodes.Ldarg_1);
                        ilgeneratorEquals.Emit(OpCodes.Isinst, tb.AsType());
                        ilgeneratorEquals.Emit(OpCodes.Stloc_0);
                        ilgeneratorEquals.Emit(OpCodes.Ldloc_0);

                        Label equalsLabel = ilgeneratorEquals.DefineLabel();

                        // GetHashCode()
                        MethodBuilder getHashCode = tb.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int), EmptyTypes);
                        getHashCode.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
                        ILGenerator ilgeneratorGetHashCode = getHashCode.GetILGenerator();
                        ilgeneratorGetHashCode.DeclareLocal(typeof(int));

                        if (names.Length == 0)
                        {
                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4_0);
                        }
                        else
                        {
                            // As done by Roslyn
                            // Note that initHash can vary, because string.GetHashCode() isn't "stable" for different compilation of the code
                            int initHash = 0;

                            for (int i = 0; i < names.Length; i++)
                            {
                                initHash = unchecked (initHash * (-1521134295) + fields[i].Name.GetHashCode());
                            }

                            // Note that the CSC seems to generate a different seed for every anonymous class
                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, initHash);
                        }

                        for (int i = 0; i < names.Length; i++)
                        {
                            Type equalityComparerT = EqualityComparer.MakeGenericType(generics[i].AsType());

                            // Equals()
                            MethodInfo equalityComparerTDefault = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerDefault);
                            MethodInfo equalityComparerTEquals  = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerEquals);

                            // Illegal one-byte branch at position: 9. Requested branch was: 143.
                            // So replace OpCodes.Brfalse_S to OpCodes.Brfalse
                            ilgeneratorEquals.Emit(OpCodes.Brfalse, equalsLabel);
                            ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault);
                            ilgeneratorEquals.Emit(OpCodes.Ldarg_0);
                            ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
                            ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
                            ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
                            ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals);

                            // GetHashCode();
                            MethodInfo equalityComparerTGetHashCode = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerGetHashCode);
                            ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295);
                            ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
                            ilgeneratorGetHashCode.Emit(OpCodes.Mul);
                            ilgeneratorGetHashCode.Emit(OpCodes.Call, equalityComparerTDefault);
                            ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0);
                            ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fields[i]);
                            ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, equalityComparerTGetHashCode);
                            ilgeneratorGetHashCode.Emit(OpCodes.Add);

                            // ToString();
                            ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                            ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? $"{{ {names[i]} = " : $", {names[i]} = ");
                            ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
                            ilgeneratorToString.Emit(OpCodes.Pop);
                            ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                            ilgeneratorToString.Emit(OpCodes.Ldarg_0);
                            ilgeneratorToString.Emit(OpCodes.Ldfld, fields[i]);
                            ilgeneratorToString.Emit(OpCodes.Box, generics[i].AsType());
                            ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendObject);
                            ilgeneratorToString.Emit(OpCodes.Pop);
                        }

                        // Only create the default and with params constructor when there are any params.
                        // Otherwise default constructor is not needed because it matches the default
                        // one provided by the runtime when no constructor is present
                        if (createParameterCtor && names.Any())
                        {
                            // .ctor default
                            ConstructorBuilder constructorDef = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, EmptyTypes);
                            constructorDef.SetCustomAttribute(DebuggerHiddenAttributeBuilder);

                            ILGenerator ilgeneratorConstructorDef = constructorDef.GetILGenerator();
                            ilgeneratorConstructorDef.Emit(OpCodes.Ldarg_0);
                            ilgeneratorConstructorDef.Emit(OpCodes.Call, ObjectCtor);
                            ilgeneratorConstructorDef.Emit(OpCodes.Ret);

                            // .ctor with params
                            ConstructorBuilder constructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, generics.Select(p => p.AsType()).ToArray());
                            constructor.SetCustomAttribute(DebuggerHiddenAttributeBuilder);

                            ILGenerator ilgeneratorConstructor = constructor.GetILGenerator();
                            ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
                            ilgeneratorConstructor.Emit(OpCodes.Call, ObjectCtor);

                            for (int i = 0; i < names.Length; i++)
                            {
                                constructor.DefineParameter(i + 1, ParameterAttributes.None, names[i]);
                                ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);

                                if (i == 0)
                                {
                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_1);
                                }
                                else if (i == 1)
                                {
                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_2);
                                }
                                else if (i == 2)
                                {
                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_3);
                                }
                                else if (i < 255)
                                {
                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_S, (byte)(i + 1));
                                }
                                else
                                {
                                    // Ldarg uses a ushort, but the Emit only accepts short, so we use a unchecked(...), cast to short and let the CLR interpret it as ushort.
                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg, unchecked ((short)(i + 1)));
                                }

                                ilgeneratorConstructor.Emit(OpCodes.Stfld, fields[i]);
                            }

                            ilgeneratorConstructor.Emit(OpCodes.Ret);
                        }

                        // Equals()
                        if (names.Length == 0)
                        {
                            ilgeneratorEquals.Emit(OpCodes.Ldnull);
                            ilgeneratorEquals.Emit(OpCodes.Ceq);
                            ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
                            ilgeneratorEquals.Emit(OpCodes.Ceq);
                        }
                        else
                        {
                            ilgeneratorEquals.Emit(OpCodes.Ret);
                            ilgeneratorEquals.MarkLabel(equalsLabel);
                            ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
                        }

                        ilgeneratorEquals.Emit(OpCodes.Ret);

                        // GetHashCode()
                        ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
                        ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
                        ilgeneratorGetHashCode.Emit(OpCodes.Ret);

                        // ToString()
                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                        ilgeneratorToString.Emit(OpCodes.Ldstr, names.Length == 0 ? "{ }" : " }");
                        ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
                        ilgeneratorToString.Emit(OpCodes.Pop);
                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                        ilgeneratorToString.Emit(OpCodes.Callvirt, ObjectToString);
                        ilgeneratorToString.Emit(OpCodes.Ret);

                        type = tb.CreateType();

                        type = GeneratedTypes.GetOrAdd(key, type);
                    }
                }
            }

            if (types.Length != 0)
            {
                type = type.MakeGenericType(types);
            }

            return(type);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Implements the specified Interface on a given SysComponent source. Outputs the instanced type
        /// with properties copied from the specified source
        /// </summary>
        /// <param name="Interface">Interface Type parameter, can be inherited type</param>
        /// <param name="source">The instance containing the loaded model</param>
        /// <returns></returns>
        public static object DynamicInterfaceImplementation(Type Interface, SysComponent source)
        {
            Type newType = null;

            //Try to retrieve earlier implementation of the specified interface
            if (Implementations.TryGetValue(Interface, out newType))
            {
                //Retrieve constructor parameters to be used in the new type instance
                if (Parameters.TryGetValue(newType, out List <TypeHelper> parameters))
                {
                }
                //Instantiate the new type, using the results from GenerateParameters with the found constructor
                //GenerateParameters returns a List of delegates, used to bind methods to the model.
                var instance = Activator.CreateInstance(newType, GenerateParameters(parameters, source, ref newType).ToArray());
                if (source == null)
                {
                    return(instance);
                }
                else
                {
                    return(BindToInstance(source, (ISysComponent)instance));
                }
            }
            else
            {
                var             name     = Guid.NewGuid().ToString();
                AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.Run);
                ModuleBuilder   module   = assembly.DefineDynamicModule(name);

                TypeBuilder        type        = module.DefineType(typeof(SysComponent).Name + "_" + Interface.Name, TypeAttributes.Public, typeof(SysComponent));
                ConstructorBuilder cstrBuilder = type.DefineConstructor(MethodAttributes.Public
                                                                        | MethodAttributes.HideBySig | MethodAttributes.SpecialName
                                                                        | MethodAttributes.RTSpecialName, CallingConventions.Standard, GetConstructorParams(Interface));
                var cstrGenerator = cstrBuilder.GetILGenerator();
                //Load "This" instance reference
                cstrGenerator.Emit(OpCodes.Ldarg_0);
                //Call the default constructor for the type
                cstrGenerator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

                var    fieldsList = new List <string>();
                var    paramList  = new List <TypeHelper>();
                Type[] interfaces = Interface.GetInterfaces();
                var    index      = 0;
                foreach (var ancestor in interfaces)
                {
                    ImplementInterface(ancestor, ref fieldsList, ref type, ref cstrBuilder, ref cstrGenerator, ref paramList, ref index);
                }
                ImplementInterface(Interface, ref fieldsList, ref type, ref cstrBuilder, ref cstrGenerator, ref paramList, ref index);
                //Return from the constructor
                cstrGenerator.Emit(OpCodes.Ret);
                newType = type.CreateType();
                Implementations.Add(Interface, newType);
                Parameters.Add(newType, paramList);
                var parameterList = new List <dynamic>();
                parameterList = GenerateParameters(paramList, source, ref newType);

                var instance = Activator.CreateInstance(newType, parameterList.ToArray());
                if (source == null)
                {
                    return(instance);
                }
                else
                {
                    return(BindToInstance(source, (ISysComponent)instance));
                    //return BindToInstance(Interface, ret);
                }
            }
        }
        private static CreateTypeResult CreateProxyType(Type proxyDefinitionType, Type targetType)
        {
            lock (_locker)
            {
                try
                {
                    // Define parent type, interface types
                    Type           parentType;
                    TypeAttributes typeAttributes;
                    Type[]         interfaceTypes;
                    if (proxyDefinitionType.IsInterface || proxyDefinitionType.IsValueType)
                    {
                        // If the proxy type definition is an interface we create an struct proxy
                        // If the proxy type definition is an struct then we use that struct to copy the values from the target type
                        parentType     = typeof(ValueType);
                        typeAttributes = TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.SequentialLayout | TypeAttributes.Sealed | TypeAttributes.Serializable;
                        if (proxyDefinitionType.IsInterface)
                        {
                            interfaceTypes = new[] { proxyDefinitionType, typeof(IDuckType) };
                        }
                        else
                        {
                            interfaceTypes = new[] { typeof(IDuckType) };
                        }
                    }
                    else
                    {
                        // If the proxy type definition is a class then we create a class proxy
                        parentType     = proxyDefinitionType;
                        typeAttributes = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout | TypeAttributes.Sealed;
                        interfaceTypes = new[] { typeof(IDuckType) };
                    }

                    // Gets the module builder
                    var moduleBuilder = GetModuleBuilder(targetType, (targetType.IsPublic || targetType.IsNestedPublic) && (proxyDefinitionType.IsPublic || proxyDefinitionType.IsNestedPublic));

                    // Ensure visibility
                    EnsureTypeVisibility(moduleBuilder, targetType);
                    EnsureTypeVisibility(moduleBuilder, proxyDefinitionType);

                    string assembly = string.Empty;
                    if (targetType.Assembly != null)
                    {
                        // Include target assembly name and public token.
                        AssemblyName asmName = targetType.Assembly.GetName();
                        assembly = asmName.Name;
                        byte[] pbToken = asmName.GetPublicKeyToken();
                        assembly += "__" + BitConverter.ToString(pbToken).Replace("-", string.Empty);
                        assembly  = assembly.Replace(".", "_").Replace("+", "__");
                    }

                    // Create a valid type name that can be used as a member of a class. (BenchmarkDotNet fails if is an invalid name)
                    string proxyTypeName = $"{assembly}.{targetType.FullName.Replace(".", "_").Replace("+", "__")}.{proxyDefinitionType.FullName.Replace(".", "_").Replace("+", "__")}_{++_typeCount}";

                    // Create Type
                    TypeBuilder proxyTypeBuilder = moduleBuilder.DefineType(
                        proxyTypeName,
                        typeAttributes,
                        parentType,
                        interfaceTypes);

                    // Create IDuckType and IDuckTypeSetter implementations
                    FieldInfo instanceField = CreateIDuckTypeImplementation(proxyTypeBuilder, targetType);

                    // Define .ctor to store the instance field
                    ConstructorBuilder ctorBuilder = proxyTypeBuilder.DefineConstructor(
                        MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                        CallingConventions.Standard,
                        new[] { instanceField.FieldType });
                    ILGenerator ctorIL = ctorBuilder.GetILGenerator();
                    ctorIL.Emit(OpCodes.Ldarg_0);
                    ctorIL.Emit(OpCodes.Ldarg_1);
                    ctorIL.Emit(OpCodes.Stfld, instanceField);
                    ctorIL.Emit(OpCodes.Ret);

                    if (proxyDefinitionType.IsValueType)
                    {
                        // Create Fields and Properties from the struct information
                        CreatePropertiesFromStruct(proxyTypeBuilder, proxyDefinitionType, targetType, instanceField);

                        // Create Type
                        Type proxyType = proxyTypeBuilder.CreateTypeInfo().AsType();
                        return(new CreateTypeResult(proxyDefinitionType, proxyType, targetType, CreateStructCopyMethod(moduleBuilder, proxyDefinitionType, proxyType, targetType), null));
                    }
                    else
                    {
                        // Create Fields and Properties
                        CreateProperties(proxyTypeBuilder, proxyDefinitionType, targetType, instanceField);

                        // Create Methods
                        CreateMethods(proxyTypeBuilder, proxyDefinitionType, targetType, instanceField);

                        // Create Type
                        Type proxyType = proxyTypeBuilder.CreateTypeInfo().AsType();
                        return(new CreateTypeResult(proxyDefinitionType, proxyType, targetType, GetCreateProxyInstanceDelegate(moduleBuilder, proxyDefinitionType, proxyType, targetType), null));
                    }
                }
                catch (Exception ex)
                {
                    return(new CreateTypeResult(proxyDefinitionType, null, targetType, null, ExceptionDispatchInfo.Capture(ex)));
                }
            }
        }
Exemplo n.º 12
0
        private Type CreateType(IEdmEntityType entityType)
        {
            // public class Address
            TypeBuilder typeBuilder = typeBuilders[entityType.Name];

            var raisePropertyChanged = ImplementateNotifyPropertyChanged(typeBuilder);

            ConstructorBuilder constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);

            ILGenerator constructorIL = constructor.GetILGenerator();

            constructorIL.Emit(OpCodes.Ldarg_0);
            ConstructorInfo superConstructor = typeof(Object).GetConstructor(new Type[0]);

            constructorIL.Emit(OpCodes.Call, superConstructor);

            object[] keys = entityType.Key().Select(p => p.Name).ToArray();
            var      dataServiceKeyBuilder = new CustomAttributeBuilder(typeof(DataServiceKeyAttribute).GetConstructor(new[] { typeof(string) }), keys);

            typeBuilder.SetCustomAttribute(dataServiceKeyBuilder);

            //var entitySetName = entityType.Name.InflectTo().Pluralized;
            //var entitySetBuilder = new CustomAttributeBuilder(typeof(EntitySetAttribute).GetConstructor(new[] { typeof(string) }), new object[] { entitySetName });
            //typeBuilder.SetCustomAttribute(entitySetBuilder);

            // Define fields and properties
            List <PropertyBuilder> propertyBuilders = new List <PropertyBuilder>();

            foreach (var property in entityType.Properties())
            {
                Type fieldType = null;
                var  typeKind  = property.Type.TypeKind();
                switch (typeKind)
                {
                case EdmTypeKind.Primitive:
                    fieldType = GetClrEquivalentType(property.Type);
                    break;

                case EdmTypeKind.Entity:
                {
                    string typeName = property.Type.AsEntity().EntityDefinition().Name;
                    fieldType = typeBuilders[typeName];
                }
                break;

                case EdmTypeKind.Collection:
                {
                    string typeName =
                        property.Type.AsCollection().ElementType().AsEntity().EntityDefinition().Name;
                    var elementType = typeBuilders[typeName];
                    fieldType = typeof(DataServiceCollection <>).MakeGenericType(elementType);
                }
                break;
                }
                FieldBuilder field = typeBuilder.DefineField(property.Name, fieldType, FieldAttributes.Private);

                if (typeKind == EdmTypeKind.Collection)
                {
                    constructorIL.Emit(OpCodes.Ldarg_0);
                    ConstructorInfo ctorPrep =
                        typeof(DataServiceCollection <>).GetConstructors().Single(c => c.GetParameters().Length == 2);
                    ConstructorInfo ctor = TypeBuilder.GetConstructor(fieldType, ctorPrep);
                    constructorIL.Emit(OpCodes.Ldnull);
                    constructorIL.Emit(OpCodes.Ldc_I4_0);
                    constructorIL.Emit(OpCodes.Newobj, ctor);
                    constructorIL.Emit(OpCodes.Stfld, field);
                }

                propertyBuilders.Add(CreateProperty(typeBuilder, property.Name, field, raisePropertyChanged));
            }

            constructorIL.Emit(OpCodes.Ret);

            // Override ToString
            OverrideToString(typeBuilder, propertyBuilders.ToArray());

            return(typeBuilder);
        }
Exemplo n.º 13
0
        //====================================================================
        // Creates a new managed type derived from a base type with any virtual
        // methods overriden to call out to python if the associated python
        // object has overriden the method.
        //====================================================================
        internal static Type CreateDerivedType(string name,
                                               Type baseType,
                                               string namespaceStr,
                                               string assemblyName,
                                               string moduleName = "Python.Runtime.Dynamic.dll")
        {
            if (null != namespaceStr)
            {
                name = namespaceStr + "." + name;
            }

            if (null == assemblyName)
            {
                assemblyName = Assembly.GetExecutingAssembly().FullName;
            }

            ModuleBuilder moduleBuilder = GetModuleBuilder(assemblyName, moduleName);
            TypeBuilder   typeBuilder;

            Type        baseClass  = baseType;
            List <Type> interfaces = new List <Type> {
                typeof(IPythonDerivedType)
            };

            // if the base type is an interface then use System.Object as the base class
            // and add the base type to the list of interfaces this new class will implement.
            if (baseType.IsInterface)
            {
                interfaces.Add(baseType);
                baseClass = typeof(System.Object);
            }

            typeBuilder = moduleBuilder.DefineType(name,
                                                   TypeAttributes.Public | TypeAttributes.Class,
                                                   baseClass,
                                                   interfaces.ToArray());

            ILGenerator   il;
            MethodBuilder mb;

            // add a field for storing the python object pointer
            FieldBuilder fb = typeBuilder.DefineField("__pyobj__", typeof(CLRObject), FieldAttributes.Public);

            // override any constructors
            ConstructorInfo[] constructors = baseClass.GetConstructors();
            foreach (ConstructorInfo ctor in constructors)
            {
                ParameterInfo[] parameters     = ctor.GetParameters();
                Type[]          parameterTypes = (from param in parameters select param.ParameterType).ToArray();

                // create a method for calling the original constructor
                string baseCtorName = "_" + baseType.Name + "__cinit__";
                mb = typeBuilder.DefineMethod(baseCtorName,
                                              MethodAttributes.Public |
                                              MethodAttributes.Final |
                                              MethodAttributes.HideBySig,
                                              typeof(void),
                                              parameterTypes);

                // emit the assembly for calling the original method using call instead of callvirt
                il = mb.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                for (int i = 0; i < parameters.Length; ++i)
                {
                    il.Emit(OpCodes.Ldarg, i + 1);
                }
                il.Emit(OpCodes.Call, ctor);
                il.Emit(OpCodes.Ret);

                // override the original method with a new one that dispatches to python
                ConstructorBuilder cb = typeBuilder.DefineConstructor(MethodAttributes.Public |
                                                                      MethodAttributes.ReuseSlot |
                                                                      MethodAttributes.HideBySig,
                                                                      ctor.CallingConvention,
                                                                      parameterTypes);
                il = cb.GetILGenerator();
                il.DeclareLocal(typeof(Object[]));
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldstr, baseCtorName);
                il.Emit(OpCodes.Ldc_I4, parameters.Length);
                il.Emit(OpCodes.Newarr, typeof(System.Object));
                il.Emit(OpCodes.Stloc_0);
                for (int i = 0; i < parameters.Length; ++i)
                {
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldc_I4, i);
                    il.Emit(OpCodes.Ldarg, i + 1);
                    if (parameterTypes[i].IsValueType)
                    {
                        il.Emit(OpCodes.Box, parameterTypes[i]);
                    }
                    il.Emit(OpCodes.Stelem, typeof(Object));
                }
                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeCtor"));
                il.Emit(OpCodes.Ret);
            }

            // override any virtual methods
            MethodInfo[] methods = baseType.GetMethods();
            foreach (MethodInfo method in methods)
            {
                if (!method.Attributes.HasFlag(MethodAttributes.Virtual) | method.Attributes.HasFlag(MethodAttributes.Final))
                {
                    continue;
                }

                ParameterInfo[] parameters     = method.GetParameters();
                Type[]          parameterTypes = (from param in parameters select param.ParameterType).ToArray();

                // create a method for calling the original method
                string baseMethodName = "_" + baseType.Name + "__" + method.Name;
                mb = typeBuilder.DefineMethod(baseMethodName,
                                              MethodAttributes.Public |
                                              MethodAttributes.Final |
                                              MethodAttributes.HideBySig,
                                              method.ReturnType,
                                              parameterTypes);

                // emit the assembly for calling the original method using call instead of callvirt
                il = mb.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                for (int i = 0; i < parameters.Length; ++i)
                {
                    il.Emit(OpCodes.Ldarg, i + 1);
                }
                il.Emit(OpCodes.Call, method);
                il.Emit(OpCodes.Ret);

                // override the original method with a new one that dispatches to python
                mb = typeBuilder.DefineMethod(method.Name,
                                              MethodAttributes.Public |
                                              MethodAttributes.ReuseSlot |
                                              MethodAttributes.Virtual |
                                              MethodAttributes.HideBySig,
                                              method.CallingConvention,
                                              method.ReturnType,
                                              parameterTypes);
                il = mb.GetILGenerator();
                il.DeclareLocal(typeof(Object[]));
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldstr, method.Name);
                il.Emit(OpCodes.Ldstr, baseMethodName);
                il.Emit(OpCodes.Ldc_I4, parameters.Length);
                il.Emit(OpCodes.Newarr, typeof(System.Object));
                il.Emit(OpCodes.Stloc_0);
                for (int i = 0; i < parameters.Length; ++i)
                {
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldc_I4, i);
                    il.Emit(OpCodes.Ldarg, i + 1);
                    if (parameterTypes[i].IsValueType)
                    {
                        il.Emit(OpCodes.Box, parameterTypes[i]);
                    }
                    il.Emit(OpCodes.Stelem, typeof(Object));
                }
                il.Emit(OpCodes.Ldloc_0);
                if (method.ReturnType == typeof(void))
                {
                    il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeMethodVoid"));
                }
                else
                {
                    il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeMethod").MakeGenericMethod(method.ReturnType));
                }
                il.Emit(OpCodes.Ret);
            }

            // add the destructor so the python object created in the constructor gets destroyed
            mb = typeBuilder.DefineMethod("Finalize",
                                          MethodAttributes.Family |
                                          MethodAttributes.Virtual |
                                          MethodAttributes.HideBySig,
                                          CallingConventions.Standard,
                                          typeof(void),
                                          Type.EmptyTypes);
            il = mb.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("Finalize"));
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, baseClass.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance));
            il.Emit(OpCodes.Ret);

            Type type = typeBuilder.CreateType();

            // scan the assembly so the newly added class can be imported
            Assembly assembly = Assembly.GetAssembly(type);

            AssemblyManager.ScanAssembly(assembly);

            return(type);
        }
        //====================================================================
        // GetDispatcher is responsible for creating a class that provides
        // an appropriate managed callback method for a given delegate type.
        //====================================================================

        private Type GetDispatcher(Type dtype)
        {
            // If a dispatcher type for the given delegate type has already
            // been generated, get it from the cache. The cache maps delegate
            // types to generated dispatcher types. A possible optimization
            // for the future would be to generate dispatcher types based on
            // unique signatures rather than delegate types, since multiple
            // delegate types with the same sig could use the same dispatcher.

            Object item = cache[dtype];

            if (item != null)
            {
                return((Type)item);
            }

            string name = "__" + dtype.FullName + "Dispatcher";

            name = name.Replace('.', '_');
            name = name.Replace('+', '_');
            TypeBuilder tb = codeGenerator.DefineType(name, basetype);

            // Generate a constructor for the generated type that calls the
            // appropriate constructor of the Dispatcher base type.

            MethodAttributes ma = MethodAttributes.Public |
                                  MethodAttributes.HideBySig |
                                  MethodAttributes.SpecialName |
                                  MethodAttributes.RTSpecialName;
            CallingConventions cc = CallingConventions.Standard;

            Type[]             args = { ptrtype, typetype };
            ConstructorBuilder cb   = tb.DefineConstructor(ma, cc, args);
            ConstructorInfo    ci   = basetype.GetConstructor(args);
            ILGenerator        il   = cb.GetILGenerator();

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Call, ci);
            il.Emit(OpCodes.Ret);

            // Method generation: we generate a method named "Invoke" on the
            // dispatcher type, whose signature matches the delegate type for
            // which it is generated. The method body simply packages the
            // arguments and hands them to the Dispatch() method, which deals
            // with converting the arguments, calling the Python method and
            // converting the result of the call.

            MethodInfo method = dtype.GetMethod("Invoke");

            ParameterInfo[] pi = method.GetParameters();

            Type[] signature = new Type[pi.Length];
            for (int i = 0; i < pi.Length; i++)
            {
                signature[i] = pi[i].ParameterType;
            }

            MethodBuilder mb = tb.DefineMethod(
                "Invoke",
                MethodAttributes.Public,
                method.ReturnType,
                signature
                );

            ConstructorInfo ctor     = listtype.GetConstructor(Type.EmptyTypes);
            MethodInfo      dispatch = basetype.GetMethod("Dispatch");
            MethodInfo      add      = listtype.GetMethod("Add");

            il = mb.GetILGenerator();
            il.DeclareLocal(listtype);
            il.Emit(OpCodes.Newobj, ctor);
            il.Emit(OpCodes.Stloc_0);

            for (int c = 0; c < signature.Length; c++)
            {
                Type t = signature[c];
                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Ldarg_S, (byte)(c + 1));

                if (t.IsValueType)
                {
                    il.Emit(OpCodes.Box, t);
                }

                il.Emit(OpCodes.Callvirt, add);
                il.Emit(OpCodes.Pop);
            }

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldloc_0);
            il.Emit(OpCodes.Call, dispatch);

            if (method.ReturnType == voidtype)
            {
                il.Emit(OpCodes.Pop);
            }
            else if (method.ReturnType.IsValueType)
            {
                il.Emit(OpCodes.Unbox_Any, method.ReturnType);
            }

            il.Emit(OpCodes.Ret);

            Type disp = tb.CreateType();

            cache[dtype] = disp;
            return(disp);
        }
Exemplo n.º 15
0
        public CodeGen DefineStaticConstructor()
        {
            ConstructorBuilder cb = _myType.DefineTypeInitializer();

            return(CreateCodeGen(cb, cb.GetILGenerator(), ArrayUtils.EmptyTypes));
        }
Exemplo n.º 16
0
            /// <summary>
            /// 创建 TCP 服务端
            /// </summary>
            /// <param name="type"></param>
            /// <param name="attribute"></param>
            /// <param name="serverInterfaceType"></param>
            /// <param name="serverCallType"></param>
            /// <param name="constructorParameterTypes"></param>
            /// <param name="methods"></param>
            /// <returns></returns>
            internal Type Build(Type type, ServerAttribute attribute, Type serverInterfaceType, Type serverCallType, Type[] constructorParameterTypes, Method <attributeType, methodAttributeType, serverSocketType>[] methods)
            {
                string             serverIdentity       = Interlocked.Increment(ref Metadata.Identity).toString();
                TypeBuilder        typeBuilder          = AutoCSer.Emit.Builder.Module.Builder.DefineType(Metadata.ServerTypeName + ".Emit." + type.FullName, TypeAttributes.Class | TypeAttributes.Sealed, Metadata.ServerType);
                FieldBuilder       valueFieldBuilder    = typeBuilder.DefineField("_value_", typeof(object), FieldAttributes.Private | FieldAttributes.InitOnly);
                ConstructorBuilder constructorBuilder   = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorParameterTypes);
                ILGenerator        constructorGenerator = constructorBuilder.GetILGenerator();
                Label serverAttributeNotNull            = constructorGenerator.DefineLabel();
                bool  isCallQueue = false;

                foreach (Method <attributeType, methodAttributeType, serverSocketType> method in methods)
                {
                    if (method != null && (isCallQueue |= method.Attribute.ServerTaskType == TcpServer.ServerTaskType.Queue))
                    {
                        break;
                    }
                }
                #region base(attribute, verify, log, isCallQueue)
                constructorGenerator.Emit(OpCodes.Ldarg_0);
                constructorGenerator.Emit(OpCodes.Ldarg_1);
                constructorGenerator.Emit(OpCodes.Ldarg_2);
                constructorGenerator.Emit(OpCodes.Ldarg_S, 4);
                constructorGenerator.int32(isCallQueue ? 1 : 0);
                constructorGenerator.Emit(OpCodes.Call, Metadata.ServerConstructorInfo);
                #endregion
                #region _value_ = value;
                constructorGenerator.Emit(OpCodes.Ldarg_0);
                constructorGenerator.Emit(OpCodes.Ldarg_3);
                constructorGenerator.Emit(OpCodes.Stfld, valueFieldBuilder);
                #endregion
                constructorGenerator.Emit(OpCodes.Ret);

                ConstructorBuilder staticConstructorBuilder   = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, null);
                ILGenerator        staticConstructorGenerator = staticConstructorBuilder.GetILGenerator();
                #region public override bool DoCommand(int index, AutoCSer.Net.TcpInternalSimpleServer.ServerSocket socket, ref SubArray<byte> data)
                MethodBuilder doCommandMethodBuilder = typeBuilder.DefineMethod("DoCommand", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot, typeof(bool), Metadata.DoCommandParameterTypes);
                #endregion
                ILGenerator doCommandGenerator = doCommandMethodBuilder.GetILGenerator();
                doCommandGenerator.DeclareLocal(typeof(int));
                Label   doCommandReturnLabel = doCommandGenerator.DefineLabel();
                Label[] doCommandLabels      = new Label[methods.Length];
                int     doCommandLabelIndex  = 0;
                foreach (Method <attributeType, methodAttributeType, serverSocketType> method in methods)
                {
                    doCommandLabels[doCommandLabelIndex++] = method == null ? doCommandReturnLabel : (method.DoCommandLabel = doCommandGenerator.DefineLabel());
                }
                #region switch (index - @CommandStartIndex)
                doCommandGenerator.Emit(OpCodes.Ldarg_1);
                doCommandGenerator.int32(TcpServer.Server.CommandStartIndex);
                doCommandGenerator.Emit(OpCodes.Sub);
                doCommandGenerator.Emit(OpCodes.Stloc_0);
                doCommandGenerator.Emit(OpCodes.Ldloc_0);
                doCommandGenerator.Emit(OpCodes.Switch, doCommandLabels);
                doCommandGenerator.MarkLabel(doCommandReturnLabel);
                doCommandGenerator.int32(0);
                doCommandGenerator.Emit(OpCodes.Ret);
                #endregion
                Outputs = new TcpSimpleServer.OutputInfo[methods.Length];
                FieldInfo outputsField = serverInterfaceType.GetField("Outputs", BindingFlags.Static | BindingFlags.NonPublic);
                foreach (Method <attributeType, methodAttributeType, serverSocketType> method in methods)
                {
                    if (method != null)
                    {
                        FieldBuilder outputInfoFieldBuilder;
                        if (method.OutputParameterType == null && !method.IsAsynchronousCallback)
                        {
                            outputInfoFieldBuilder = null;
                        }
                        else
                        {
                            TcpSimpleServer.OutputInfo outputInfo = new TcpSimpleServer.OutputInfo();
                            Outputs[method.Attribute.CommandIdentity] = outputInfo;
                            if (method.OutputParameterType != null)
                            {
                                outputInfo.OutputParameterIndex = method.OutputParameterType.Index;
                                if (attribute.IsSimpleSerialize)
                                {
                                    outputInfo.IsSimpleSerializeOutputParamter = method.OutputParameterType.IsSimpleSerialize && SimpleSerialize.Serializer.IsType(method.ReturnType);
                                }
                            }
                            #region private static readonly AutoCSer.Net.TcpSimpleServer.OutputInfo @MethodIdentityCommand = AutoCSer.Net.TcpInternalSimpleServer.Emit.Server<interfaceType>.Outputs[@CommandIdentity];
                            staticConstructorGenerator.Emit(OpCodes.Ldsfld, outputsField);
                            staticConstructorGenerator.int32(method.Attribute.CommandIdentity);
                            staticConstructorGenerator.Emit(OpCodes.Ldelem_Ref);
                            staticConstructorGenerator.Emit(OpCodes.Stsfld, outputInfoFieldBuilder = typeBuilder.DefineField("_o" + method.Attribute.CommandIdentity.toString(), typeof(TcpServer.OutputInfo), FieldAttributes.Private | FieldAttributes.InitOnly | FieldAttributes.Static));
                            #endregion
                        }
                        ParameterInfo[] parameters = method.MethodInfo.GetParameters();
                        TypeBuilder     serverCallTypeBuilder;
                        FieldInfo       returnTypeField  = method.ReturnValueType == null ? null : (method.ReturnValueType == typeof(TcpServer.ReturnValue) ? TcpServer.Emit.ServerMetadata.ReturnValueTypeField : method.ReturnValueType.GetField(TcpServer.Emit.ServerMetadata.ReturnValueTypeField.Name, BindingFlags.Instance | BindingFlags.Public));
                        FieldInfo       returnValueField = method.ReturnValueType == null ? null : method.ReturnValueType.GetField("Value", BindingFlags.Instance | BindingFlags.Public);
                        if (method.IsMethodServerCall)
                        {
                            Type      baseType            = method.ParameterType == null ? Metadata.ServerCallType : serverCallType.MakeGenericType(method.ParameterType.Type);
                            FieldInfo inputParameterField = method.ParameterType == null ? null : baseType.GetField("inputParameter", BindingFlags.Instance | BindingFlags.NonPublic);
                            serverCallTypeBuilder = typeBuilder.DefineNestedType(Metadata.ServerCallTypeName + ".Emit." + serverIdentity + "_" + method.Attribute.CommandIdentity.toString(), TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPublic, baseType);
                            Type      returnOutputType       = method.OutputParameterType == null ? typeof(AutoCSer.Net.TcpServer.ReturnValue) : typeof(AutoCSer.Net.TcpServer.ReturnValue <>).MakeGenericType(method.OutputParameterType.Type);
                            FieldInfo returnOutputValueField = method.OutputParameterType == null ? null : returnOutputType.GetField("Value", BindingFlags.Instance | BindingFlags.Public);
                            Type      returnOutputRefType    = returnOutputType.MakeByRefType();
                            #region private void get(ref AutoCSer.Net.TcpServer.ReturnValue<@OutputParameterTypeName> value)
                            MethodBuilder getMethodBuilder = serverCallTypeBuilder.DefineMethod("get", MethodAttributes.Private, typeof(void), new Type[] { returnOutputRefType });
                            #endregion
                            ILGenerator  getGenerator               = getMethodBuilder.GetILGenerator();
                            Label        getReturnLabel             = getGenerator.DefineLabel();
                            LocalBuilder exceptionErrorLocalBuilder = getGenerator.DeclareLocal(typeof(Exception));
                            #region try
                            getGenerator.BeginExceptionBlock();
                            #endregion
                            #region @MethodReturnType.FullName @ReturnName = serverValue.@MethodName(Socket, inputParameter.@ParameterName);
                            LocalBuilder returnLocalBuilder = method.IsReturnType ? getGenerator.DeclareLocal(method.ReturnValueType ?? method.ReturnType) : null;
                            getGenerator.Emit(OpCodes.Ldarg_0);
                            getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallServerValueField);
                            foreach (ParameterInfo parameter in parameters)
                            {
                                if (SimpleParameterType.IsInputParameter(parameter))
                                {
                                    getGenerator.Emit(OpCodes.Ldarg_0);
                                    getGenerator.Emit(OpCodes.Ldflda, inputParameterField);
                                    getGenerator.Emit(parameter.ParameterType.IsByRef ? OpCodes.Ldflda : OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name));
                                }
                                else if (parameter.IsOut)
                                {
                                    getGenerator.Emit(OpCodes.Ldarg_1);
                                    getGenerator.Emit(OpCodes.Ldflda, returnOutputValueField);
                                    getGenerator.Emit(OpCodes.Ldflda, method.OutputParameterType.GetField(parameter.Name));
                                }
                                else if (parameter.ParameterType == Metadata.SocketType)
                                {
                                    getGenerator.Emit(OpCodes.Ldarg_0);
                                    getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField);
                                }
                                else
                                {
                                    getGenerator.Emit(OpCodes.Ldnull);
                                }
                            }
                            getGenerator.call(method.MethodInfo);
                            if (method.IsReturnType)
                            {
                                getGenerator.Emit(OpCodes.Stloc_S, returnLocalBuilder);
                            }
                            #endregion
                            FieldInfo returnValueTypeField = method.OutputParameterType == null ? TcpServer.Emit.ServerMetadata.ReturnValueTypeField : returnOutputType.GetField(TcpServer.Emit.ServerMetadata.ReturnValueTypeField.Name, BindingFlags.Instance | BindingFlags.Public);
                            if (method.OutputParameterType == null)
                            {
                                if (method.ReturnValueType != null)
                                {
                                    Label returnTypeErrorLabel = getGenerator.DefineLabel();
                                    #region if(@ReturnName.Type != AutoCSer.Net.TcpServer.ReturnType.Success)
                                    getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                    getGenerator.Emit(OpCodes.Ldfld, returnTypeField);
                                    getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success);
                                    getGenerator.Emit(OpCodes.Beq_S, returnTypeErrorLabel);
                                    #endregion
                                    #region value.Type = @ReturnName.Type;
                                    getGenerator.Emit(OpCodes.Ldarg_1);
                                    getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                    getGenerator.Emit(OpCodes.Ldfld, returnTypeField);
                                    getGenerator.Emit(OpCodes.Stfld, returnValueTypeField);
                                    #endregion
                                    getGenerator.Emit(OpCodes.Leave_S, getReturnLabel);
                                    getGenerator.MarkLabel(returnTypeErrorLabel);
                                }
                                #region value.Type = AutoCSer.Net.TcpServer.ReturnType.Success;
                                getGenerator.Emit(OpCodes.Ldarg_1);
                                getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success);
                                getGenerator.Emit(OpCodes.Stfld, returnValueTypeField);
                                #endregion
                                getGenerator.Emit(OpCodes.Leave_S, getReturnLabel);
                            }
                            else
                            {
                                Label returnTypeErrorLabel;
                                if (method.ReturnValueType == null)
                                {
                                    returnTypeErrorLabel = default(Label);
                                }
                                else
                                {
                                    #region if(@ReturnName.Type != AutoCSer.Net.TcpServer.ReturnType.Success)
                                    getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                    getGenerator.Emit(OpCodes.Ldfld, returnTypeField);
                                    getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success);
                                    getGenerator.Emit(OpCodes.Bne_Un, returnTypeErrorLabel = getGenerator.DefineLabel());
                                    #endregion
                                }
                                if (method.Attribute.IsVerifyMethod)
                                {
                                    Label verifyEndLabel = getGenerator.DefineLabel();
                                    #region if (@ReturnName / @ReturnName.Value)
                                    if (method.ReturnValueType == null)
                                    {
                                        getGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder);
                                    }
                                    else
                                    {
                                        getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                        getGenerator.Emit(OpCodes.Ldfld, returnValueField);
                                    }
                                    getGenerator.Emit(OpCodes.Brfalse_S, verifyEndLabel);
                                    #endregion
                                    #region Socket.SetVerifyMethod();
                                    getGenerator.Emit(OpCodes.Ldarg_0);
                                    getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField);
                                    getGenerator.call(ServerMetadata.ServerSocketSetVerifyMethodMethod);
                                    #endregion
                                    getGenerator.MarkLabel(verifyEndLabel);
                                }
                                LocalBuilder valueLocalBuilder = getGenerator.DeclareLocal(method.OutputParameterType.Type);
                                #region value.Value.@ParameterName = inputParameter.@ParameterName;
                                foreach (ParameterInfo parameter in method.OutputParameters)
                                {
                                    if (!parameter.IsOut)
                                    {
                                        getGenerator.Emit(OpCodes.Ldarg_1);
                                        getGenerator.Emit(OpCodes.Ldflda, returnOutputValueField);
                                        getGenerator.Emit(OpCodes.Ldarg_0);
                                        getGenerator.Emit(OpCodes.Ldflda, inputParameterField);
                                        getGenerator.Emit(OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name));
                                        getGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(parameter.Name));
                                    }
                                }
                                #endregion
                                if (method.ReturnType != typeof(void))
                                {
                                    #region value.Value.@ReturnName = @ReturnName / @ReturnName.Value;
                                    getGenerator.Emit(OpCodes.Ldarg_1);
                                    getGenerator.Emit(OpCodes.Ldflda, returnOutputValueField);
                                    if (method.ReturnValueType == null)
                                    {
                                        getGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder);
                                    }
                                    else
                                    {
                                        getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                        getGenerator.Emit(OpCodes.Ldfld, returnValueField);
                                    }
                                    getGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(TcpServer.ReturnValue.RetParameterName));
                                    #endregion
                                }
                                #region value.Type = AutoCSer.Net.TcpServer.ReturnType.Success;
                                getGenerator.Emit(OpCodes.Ldarg_1);
                                getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success);
                                getGenerator.Emit(OpCodes.Stfld, returnValueTypeField);
                                #endregion
                                getGenerator.Emit(OpCodes.Leave_S, getReturnLabel);
                                if (method.ReturnValueType != null)
                                {
                                    getGenerator.MarkLabel(returnTypeErrorLabel);
                                    #region value.Type = @ReturnName.Type;
                                    getGenerator.Emit(OpCodes.Ldarg_1);
                                    getGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                    getGenerator.Emit(OpCodes.Ldfld, returnTypeField);
                                    getGenerator.Emit(OpCodes.Stfld, returnValueTypeField);
                                    #endregion
                                    getGenerator.Emit(OpCodes.Leave_S, getReturnLabel);
                                }
                            }
                            #region catch (Exception error)
                            getGenerator.BeginCatchBlock(typeof(Exception));
                            getGenerator.Emit(OpCodes.Stloc_S, exceptionErrorLocalBuilder);
                            #endregion
                            #region value.Type = AutoCSer.Net.TcpServer.ReturnType.ServerException;
                            getGenerator.Emit(OpCodes.Ldarg_1);
                            getGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.ServerException);
                            getGenerator.Emit(OpCodes.Stfld, returnValueTypeField);
                            #endregion
                            #region Socket.Log(error);
                            getGenerator.Emit(OpCodes.Ldarg_0);
                            getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField);
                            getGenerator.Emit(OpCodes.Ldloc_S, exceptionErrorLocalBuilder);
                            getGenerator.call(Metadata.ServerSocketLogMethod);
                            #endregion
                            getGenerator.Emit(OpCodes.Leave_S, getReturnLabel);
                            #region try end
                            getGenerator.EndExceptionBlock();
                            #endregion
                            getGenerator.MarkLabel(getReturnLabel);
                            getGenerator.Emit(OpCodes.Ret);

                            #region public override void Call()
                            MethodBuilder callMethodBuilder = serverCallTypeBuilder.DefineMethod("Call", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot, typeof(void), null);
                            #endregion
                            ILGenerator callGenerator = callMethodBuilder.GetILGenerator();
                            #region AutoCSer.Net.TcpInternalSimpleServer.ServerSocket socket = Socket;
                            LocalBuilder socketBuilder = callGenerator.DeclareLocal(typeof(serverSocketType));
                            getGenerator.Emit(OpCodes.Ldarg_0);
                            getGenerator.Emit(OpCodes.Ldfld, Metadata.ServerCallSocketField);
                            callGenerator.Emit(OpCodes.Stloc_S, socketBuilder);
                            #endregion
                            #region AutoCSer.Net.TcpServer.ReturnValue<@OutputParameterTypeName> value = new AutoCSer.Net.TcpServer.ReturnValue<@OutputParameterTypeName>();
                            LocalBuilder valueBuilder = callGenerator.DeclareLocal(returnOutputType);
                            if (method.OutputParameterType == null || method.Attribute.IsInitobj || method.OutputParameterType.IsInitobj)
                            {
                                callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder);
                                callGenerator.Emit(OpCodes.Initobj, returnOutputType);
                            }
                            else
                            {
                                callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder);
                                callGenerator.int32(0);
                                callGenerator.Emit(OpCodes.Stfld, returnValueTypeField);
                            }
                            #endregion
                            #region get(ref value);
                            callGenerator.Emit(OpCodes.Ldarg_0);
                            callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder);
                            callGenerator.call(getMethodBuilder);
                            #endregion
                            #region push(this);
                            callGenerator.Emit(OpCodes.Ldarg_0);
                            callGenerator.Emit(OpCodes.Ldarg_0);
                            callGenerator.call((method.ParameterType == null ? Metadata.ServerCallPushMethod : serverCallType.MakeGenericType(method.ParameterType.Type).GetMethod("push", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)).MakeGenericMethod(serverCallTypeBuilder));
                            #endregion
                            if (method.OutputParameterType == null)
                            {
                                #region socket.SendAsync(value.Type);
                                callGenerator.Emit(OpCodes.Ldloc_S, socketBuilder);
                                callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder);
                                callGenerator.Emit(OpCodes.Ldfld, returnValueTypeField);
                                callGenerator.call(Metadata.ServerSocketSendAsyncMethod);
                                callGenerator.Emit(OpCodes.Pop);
                                #endregion
                            }
                            else
                            {
                                #region socket.SendAsync(@MethodIdentityCommand, ref value);
                                callGenerator.Emit(OpCodes.Ldloc_S, socketBuilder);
                                callGenerator.Emit(OpCodes.Ldsfld, outputInfoFieldBuilder);
                                callGenerator.Emit(OpCodes.Ldloca_S, valueBuilder);
                                callGenerator.call(Metadata.ServerSocketSendAsyncOutputMethod.MakeGenericMethod(method.OutputParameterType.Type));
                                callGenerator.Emit(OpCodes.Pop);
                                #endregion
                            }
                            callGenerator.Emit(OpCodes.Ret);
                            serverCallTypeBuilder.CreateType();
                        }
                        else
                        {
                            serverCallTypeBuilder = null;
                        }

                        #region private bool @MethodIndexName(AutoCSer.Net.TcpInternalSimpleServer.ServerSocket socket, ref SubArray<byte> data)
                        MethodBuilder methodBuilder = typeBuilder.DefineMethod("_m" + method.Attribute.CommandIdentity.toString(), MethodAttributes.Private, typeof(bool), Metadata.MethodParameterTypes);
                        #endregion
                        ILGenerator methodGenerator = methodBuilder.GetILGenerator();
                        if (method.Attribute.IsExpired)
                        {
                            if (method.OutputParameterType == null)
                            {
                                #region return socket.Send(AutoCSer.Net.TcpServer.ReturnType.VersionExpired);
                                methodGenerator.Emit(OpCodes.Ldarg_1);
                                methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.VersionExpired);
                                methodGenerator.call(Metadata.ServerSocketSendReturnTypeMethod);
                                methodGenerator.Emit(OpCodes.Ret);
                                #endregion
                            }
                            else
                            {
                                #region return socket.SendOutput(AutoCSer.Net.TcpServer.ReturnType.VersionExpired);
                                methodGenerator.Emit(OpCodes.Ldarg_1);
                                methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.VersionExpired);
                                methodGenerator.call(Metadata.ServerSocketSendOutputReturnTypeMethod);
                                methodGenerator.Emit(OpCodes.Ret);
                                #endregion
                            }
                        }
                        else
                        {
                            Label pushLabel = methodGenerator.DefineLabel(), returnLable = methodGenerator.DefineLabel();
                            #region bool isReturnLocalBuilder = false;
                            LocalBuilder isReturnLocalBuilder = methodGenerator.DeclareLocal(typeof(bool));
                            methodGenerator.int32(0);
                            methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder);
                            #endregion
                            #region AutoCSer.Net.TcpServer.ReturnType returnType = AutoCSer.Net.TcpServer.ReturnType.Unknown;
                            LocalBuilder returnTypeLocalBuilder = methodGenerator.DeclareLocal(typeof(AutoCSer.Net.TcpServer.ReturnType));
                            methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Unknown);
                            methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder);
                            #endregion
                            #region try
                            methodGenerator.BeginExceptionBlock();
                            #endregion
                            LocalBuilder parameterLocalBuilder, outputParameterLocalBuilder = null;
                            Label        serverDeSerializeErrorLabel;
                            if (method.ParameterType == null)
                            {
                                parameterLocalBuilder       = null;
                                serverDeSerializeErrorLabel = default(Label);
                            }
                            else
                            {
                                #region @InputParameterTypeName inputParameter = new @InputParameterTypeName();
                                parameterLocalBuilder = methodGenerator.DeclareLocal(method.ParameterType.Type);
                                if (method.Attribute.IsInitobj || method.ParameterType.IsInitobj)
                                {
                                    methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder);
                                    methodGenerator.Emit(OpCodes.Initobj, method.ParameterType.Type);
                                }
                                #endregion
                                #region if (socket.DeSerialize(ref data, ref inputParameter))
                                methodGenerator.Emit(OpCodes.Ldarg_1);
                                methodGenerator.Emit(OpCodes.Ldarg_2);
                                methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder);
                                methodGenerator.int32(method.ParameterType.IsSimpleSerialize ? 1 : 0);
                                methodGenerator.call(ServerMetadata.ServerSocketDeSerializeMethod.MakeGenericMethod(method.ParameterType.Type));
                                methodGenerator.Emit(OpCodes.Brfalse, serverDeSerializeErrorLabel = methodGenerator.DefineLabel());
                                #endregion
                            }
                            if (method.IsMethodServerCall)
                            {
                                #region @MethodStreamName.Call(socket, _value_, @ServerTask, ref inputParameter);
                                methodGenerator.Emit(OpCodes.Ldarg_1);
                                methodGenerator.Emit(OpCodes.Ldarg_0);
                                methodGenerator.Emit(OpCodes.Ldfld, valueFieldBuilder);
                                methodGenerator.int32((byte)method.ServerTask);
                                if (method.ParameterType == null)
                                {
                                    methodGenerator.call(Metadata.ServerCallCallMethod.MakeGenericMethod(serverCallTypeBuilder));
                                }
                                else
                                {
                                    methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder);
                                    methodGenerator.call(serverCallType.MakeGenericType(method.ParameterType.Type).GetMethod("Call", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly).MakeGenericMethod(serverCallTypeBuilder));
                                }
                                #endregion
                                #region isReturnLocalBuilder = true;
                                methodGenerator.int32(1);
                                methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder);
                                #endregion
                            }
                            else
                            {
                                if (method.OutputParameterType != null)
                                {
                                    #region @OutputParameterTypeName outputParameter = new @OutputParameterTypeName();
                                    outputParameterLocalBuilder = methodGenerator.DeclareLocal(method.OutputParameterType.Type);
                                    if (method.Attribute.IsInitobj || method.OutputParameterType.IsInitobj)
                                    {
                                        methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder);
                                        methodGenerator.Emit(OpCodes.Initobj, method.OutputParameterType.Type);
                                    }
                                    #endregion
                                }
                                #region @MethodReturnType.FullName @ReturnName = _value_.@MethodName(socket, inputParameter.@ParameterName);
                                LocalBuilder returnLocalBuilder = method.IsReturnType ? methodGenerator.DeclareLocal(method.ReturnValueType ?? method.ReturnType) : null;
                                methodGenerator.Emit(OpCodes.Ldarg_0);
                                methodGenerator.Emit(OpCodes.Ldfld, valueFieldBuilder);
                                foreach (ParameterInfo parameter in parameters)
                                {
                                    if (SimpleParameterType.IsInputParameter(parameter))
                                    {
                                        methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder);
                                        methodGenerator.Emit(parameter.ParameterType.IsByRef ? OpCodes.Ldflda : OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name));
                                    }
                                    else if (parameter.IsOut)
                                    {
                                        methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder);
                                        methodGenerator.Emit(OpCodes.Ldflda, method.OutputParameterType.GetField(parameter.Name));
                                    }
                                    else if (parameter.ParameterType == Metadata.SocketType)
                                    {
                                        methodGenerator.Emit(OpCodes.Ldarg_1);
                                    }
                                    else
                                    {
                                        methodGenerator.Emit(OpCodes.Ldnull);
                                    }
                                }
                                methodGenerator.call(method.MethodInfo);
                                if (method.IsReturnType)
                                {
                                    methodGenerator.Emit(OpCodes.Stloc_S, returnLocalBuilder);
                                }
                                #endregion
                                if (method.OutputParameterType == null)
                                {
                                    if (method.ReturnValueType == null)
                                    {
                                        #region return socket.Send();
                                        methodGenerator.Emit(OpCodes.Ldarg_1);
                                        methodGenerator.call(Metadata.ServerSocketSendMethod);
                                        methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder);
                                        #endregion
                                    }
                                    else
                                    {
                                        #region return socket.Send(@ReturnName.Type);
                                        methodGenerator.Emit(OpCodes.Ldarg_1);
                                        methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                        methodGenerator.Emit(OpCodes.Ldfld, returnTypeField);
                                        methodGenerator.call(Metadata.ServerSocketSendReturnTypeMethod);
                                        methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder);
                                        #endregion
                                    }
                                }
                                else
                                {
                                    Label returnTypeErrorLabel;
                                    if (method.ReturnValueType == null)
                                    {
                                        returnTypeErrorLabel = default(Label);
                                    }
                                    else
                                    {
                                        #region if(@ReturnName.Type == AutoCSer.Net.TcpServer.ReturnType.Success)
                                        methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                        methodGenerator.Emit(OpCodes.Ldfld, returnTypeField);
                                        methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.Success);
                                        methodGenerator.Emit(OpCodes.Bne_Un, returnTypeErrorLabel = methodGenerator.DefineLabel());
                                        #endregion
                                    }
                                    if (method.Attribute.IsVerifyMethod)
                                    {
                                        Label verifyEndLabel = methodGenerator.DefineLabel();
                                        #region if (@ReturnName / @ReturnName.Value)
                                        if (method.ReturnValueType == null)
                                        {
                                            methodGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder);
                                        }
                                        else
                                        {
                                            methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                            methodGenerator.Emit(OpCodes.Ldfld, returnValueField);
                                        }
                                        methodGenerator.Emit(OpCodes.Brfalse_S, verifyEndLabel);
                                        #endregion
                                        #region socket.SetVerifyMethod();
                                        methodGenerator.Emit(OpCodes.Ldarg_1);
                                        methodGenerator.call(ServerMetadata.ServerSocketSetVerifyMethodMethod);
                                        #endregion
                                        methodGenerator.MarkLabel(verifyEndLabel);
                                    }
                                    foreach (ParameterInfo parameter in method.OutputParameters)
                                    {
                                        if (!parameter.IsOut)
                                        {
                                            #region outputParameter.@ParameterName = inputParameter.@ParameterName
                                            methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder);
                                            methodGenerator.Emit(OpCodes.Ldloca_S, parameterLocalBuilder);
                                            methodGenerator.Emit(OpCodes.Ldfld, method.ParameterType.GetField(parameter.Name));
                                            methodGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(parameter.Name));
                                            #endregion
                                        }
                                    }
                                    if (method.ReturnType != typeof(void))
                                    {
                                        #region _outputParameter_.Ret = @ReturnName / @ReturnName.Value
                                        methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder);
                                        if (method.ReturnValueType == null)
                                        {
                                            methodGenerator.Emit(OpCodes.Ldloc_S, returnLocalBuilder);
                                        }
                                        else
                                        {
                                            methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                            methodGenerator.Emit(OpCodes.Ldfld, returnValueField);
                                        }
                                        methodGenerator.Emit(OpCodes.Stfld, method.OutputParameterType.GetField(TcpServer.ReturnValue.RetParameterName));
                                        #endregion
                                    }

                                    #region return socket.Send(@MethodIdentityCommand, ref outputParameter)
                                    methodGenerator.Emit(OpCodes.Ldarg_1);
                                    methodGenerator.Emit(OpCodes.Ldsfld, outputInfoFieldBuilder);
                                    methodGenerator.Emit(OpCodes.Ldloca_S, outputParameterLocalBuilder);
                                    methodGenerator.call(Metadata.ServerSocketSendOutputMethod.MakeGenericMethod(method.OutputParameterType.Type));
                                    methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder);
                                    #endregion
                                    methodGenerator.Emit(OpCodes.Leave_S, returnLable);
                                    if (method.ReturnValueType != null)
                                    {
                                        methodGenerator.MarkLabel(returnTypeErrorLabel);
                                        #region return socket.SendOutput(@ReturnValue.Type);
                                        methodGenerator.Emit(OpCodes.Ldarg_1);
                                        methodGenerator.Emit(OpCodes.Ldloca_S, returnLocalBuilder);
                                        methodGenerator.Emit(OpCodes.Ldfld, returnTypeField);
                                        methodGenerator.call(Metadata.ServerSocketSendOutputReturnTypeMethod);
                                        methodGenerator.Emit(OpCodes.Stloc_S, isReturnLocalBuilder);
                                        #endregion
                                    }
                                }
                            }
                            methodGenerator.Emit(OpCodes.Leave_S, returnLable);
                            if (method.ParameterType != null)
                            {
                                methodGenerator.MarkLabel(serverDeSerializeErrorLabel);
                                #region returnType = AutoCSer.Net.TcpServer.ReturnType.ServerDeSerializeError;
                                methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.ServerDeSerializeError);
                                methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder);
                                #endregion
                                methodGenerator.Emit(OpCodes.Leave_S, pushLabel);
                            }
                            #region catch (Exception error)
                            methodGenerator.BeginCatchBlock(typeof(Exception));
                            LocalBuilder errorLocalBuilder = methodGenerator.DeclareLocal(typeof(Exception));
                            methodGenerator.Emit(OpCodes.Stloc_S, errorLocalBuilder);
                            #endregion
                            #region returnType = AutoCSer.Net.TcpServer.ReturnType.ServerException;
                            methodGenerator.int32((byte)AutoCSer.Net.TcpServer.ReturnType.ServerException);
                            methodGenerator.Emit(OpCodes.Stloc_S, returnTypeLocalBuilder);
                            #endregion
                            #region socket.Log(error);
                            methodGenerator.Emit(OpCodes.Ldarg_1);
                            methodGenerator.Emit(OpCodes.Ldloc_S, errorLocalBuilder);
                            methodGenerator.call(Metadata.ServerSocketLogMethod);
                            #endregion
                            methodGenerator.Emit(OpCodes.Leave_S, pushLabel);
                            #region try end
                            methodGenerator.EndExceptionBlock();
                            #endregion
                            methodGenerator.MarkLabel(pushLabel);
                            if (method.OutputParameterType == null)
                            {
                                #region return socket.Send(returnType);
                                methodGenerator.Emit(OpCodes.Ldarg_1);
                                methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder);
                                methodGenerator.call(Metadata.ServerSocketSendReturnTypeMethod);
                                methodGenerator.Emit(OpCodes.Ret);
                                #endregion
                            }
                            else
                            {
                                #region return socket.SendOutput(returnType);
                                methodGenerator.Emit(OpCodes.Ldarg_1);
                                methodGenerator.Emit(OpCodes.Ldloc_S, returnTypeLocalBuilder);
                                methodGenerator.call(Metadata.ServerSocketSendOutputReturnTypeMethod);
                                methodGenerator.Emit(OpCodes.Ret);
                                #endregion
                            }
                            methodGenerator.MarkLabel(returnLable);
                            methodGenerator.Emit(OpCodes.Ldloc_S, isReturnLocalBuilder);
                            methodGenerator.Emit(OpCodes.Ret);
                        }

                        #region case @MethodIndex: return @MethodIndexName(socket, ref data);
                        doCommandGenerator.MarkLabel(method.DoCommandLabel);
                        doCommandGenerator.Emit(OpCodes.Ldarg_0);
                        doCommandGenerator.Emit(OpCodes.Ldarg_2);
                        doCommandGenerator.Emit(OpCodes.Ldarg_3);
                        doCommandGenerator.call(methodBuilder);
                        doCommandGenerator.Emit(OpCodes.Ret);
                        #endregion
                        method.DoCommandLabel = default(Label);
                    }
                }
                doCommandGenerator.Emit(OpCodes.Ret);
                staticConstructorGenerator.Emit(OpCodes.Ret);

                return(typeBuilder.CreateType());
            }
Exemplo n.º 17
0
        /// <summary>
        /// 为指定接口动态创建代理类型
        /// </summary>
        /// <param name="interfaceType"></param>
        /// <returns></returns>
        private static Type DynamicallyCreateProxyType(Type interfaceType)
        {
            var    methodInfo = MethodBase.GetCurrentMethod();
            String methodName = methodInfo.Name;
            Type   objectType = typeof(Object);


            String assemblyName             = "DynamicAssembly";
            String moudleName               = "DynamicMoudle";
            String typeName                 = interfaceType.FullName + ".DynamicProxy";
            String field_handler_Name       = "_handler";
            String field_interfaceType_Name = "_interfaceType";


            //在当前程序域中构建程序集信息
            AppDomain domain = AppDomain.CurrentDomain;

            //构建一个程序集
            AssemblyName assemblyNameObj = new AssemblyName(assemblyName);

            assemblyNameObj.Version     = new Version(1, 0, 0, 0);
            assemblyNameObj.CultureInfo = null;
#if NET40
            AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(
                assemblyNameObj,
                AssemblyBuilderAccess.RunAndCollect);
#else
            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
                assemblyNameObj,
                AssemblyBuilderAccess.RunAndCollect);
#endif
            //在程序集中构建基本模块
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moudleName);

            //在模块中构建类型
            TypeBuilder typeBuilder = moduleBuilder.DefineType(
                typeName,
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed,
                objectType,
                new Type[] { interfaceType, typeof(IDisposable) });

            //为类型构建字段成员
            FieldBuilder handlerField = typeBuilder.DefineField(
                field_handler_Name,
                typeof(IInvokeHandler),
                FieldAttributes.Private);

            FieldBuilder interfaceTypeField = typeBuilder.DefineField(
                field_interfaceType_Name,
                interfaceType,
                FieldAttributes.Private);

            //为类型构建构造函数信息
            ConstructorInfo objectConstructorInfo = objectType.GetConstructor(new Type[] { });

            //public DynamicProxy(IDynamicProxyHandler handler,Type interfaceType)
            ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                new Type[] { typeof(IInvokeHandler), typeof(Type) });

            ILGenerator iLGenerator = constructorBuilder.GetILGenerator();

            //在构造函数中使用参数为私有字赋值

            //this._handler=handler;
            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.Emit(OpCodes.Ldarg_1);
            iLGenerator.Emit(OpCodes.Stfld, handlerField);

            //this._interfaceType=interfaceType;
            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.Emit(OpCodes.Ldarg_2);
            iLGenerator.Emit(OpCodes.Stfld, interfaceTypeField);

            //调用基类的构造函数
            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.Emit(OpCodes.Call, objectConstructorInfo);
            iLGenerator.Emit(OpCodes.Ret);


            //为类型构建方法成员
            DynamicallyCreateProxyTypeMethod(interfaceType, typeBuilder, handlerField, interfaceTypeField);
            DynamicallyCreateProxyTypeMethod(typeof(IDisposable), typeBuilder, handlerField, interfaceTypeField);

#if NET40
            return(typeBuilder.CreateType());
#else
            return(typeBuilder.CreateTypeInfo());
#endif
        }
Exemplo n.º 18
0
    public static Type BuildDynAssembly()
    {
        Type pointType = null;

        AppDomain currentDom = Thread.GetDomain();

        Console.Write("Please enter a name for your new assembly: ");
        StringBuilder asmFileNameBldr = new StringBuilder();

        asmFileNameBldr.Append(Console.ReadLine());
        asmFileNameBldr.Append(".exe");
        string asmFileName = asmFileNameBldr.ToString();

        AssemblyName myAsmName = new AssemblyName();

        myAsmName.Name = "MyDynamicAssembly";

        AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
            myAsmName,
            AssemblyBuilderAccess.RunAndSave);

        // We've created a dynamic assembly space - now, we need to create a module
        // within it to reflect the type Point into.

        ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule(asmFileName,
                                                                   asmFileName);

        TypeBuilder myTypeBldr = myModuleBldr.DefineType("Point");

        FieldBuilder xField = myTypeBldr.DefineField("x", typeof(int),
                                                     FieldAttributes.Private);
        FieldBuilder yField = myTypeBldr.DefineField("y", typeof(int),
                                                     FieldAttributes.Private);

        // Build the constructor.

        Type            objType = Type.GetType("System.Object");
        ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);

        Type[]             ctorParams = new Type[] { typeof(int), typeof(int) };
        ConstructorBuilder pointCtor  = myTypeBldr.DefineConstructor(
            MethodAttributes.Public,
            CallingConventions.Standard,
            ctorParams);
        ILGenerator ctorIL = pointCtor.GetILGenerator();

        ctorIL.Emit(OpCodes.Ldarg_0);
        ctorIL.Emit(OpCodes.Call, objCtor);
        ctorIL.Emit(OpCodes.Ldarg_0);
        ctorIL.Emit(OpCodes.Ldarg_1);
        ctorIL.Emit(OpCodes.Stfld, xField);
        ctorIL.Emit(OpCodes.Ldarg_0);
        ctorIL.Emit(OpCodes.Ldarg_2);
        ctorIL.Emit(OpCodes.Stfld, yField);
        ctorIL.Emit(OpCodes.Ret);

        // Build the DotProduct method.

        Console.WriteLine("Constructor built.");

        MethodBuilder pointDPBldr = myTypeBldr.DefineMethod("DotProduct",
                                                            MethodAttributes.Public,
                                                            typeof(int),
                                                            new Type[] { myTypeBldr });

        ILGenerator dpIL = pointDPBldr.GetILGenerator();

        dpIL.Emit(OpCodes.Ldarg_0);
        dpIL.Emit(OpCodes.Ldfld, xField);
        dpIL.Emit(OpCodes.Ldarg_1);
        dpIL.Emit(OpCodes.Ldfld, xField);
        dpIL.Emit(OpCodes.Mul_Ovf_Un);
        dpIL.Emit(OpCodes.Ldarg_0);
        dpIL.Emit(OpCodes.Ldfld, yField);
        dpIL.Emit(OpCodes.Ldarg_1);
        dpIL.Emit(OpCodes.Ldfld, yField);
        dpIL.Emit(OpCodes.Mul_Ovf_Un);
        dpIL.Emit(OpCodes.Add_Ovf_Un);
        dpIL.Emit(OpCodes.Ret);

        // Build the PointMain method.

        Console.WriteLine("DotProduct built.");

        MethodBuilder pointMainBldr = myTypeBldr.DefineMethod("PointMain",
                                                              MethodAttributes.Public |
                                                              MethodAttributes.Static,
                                                              typeof(void),
                                                              null);

        pointMainBldr.InitLocals = true;
        ILGenerator pmIL = pointMainBldr.GetILGenerator();

        // We have four methods that we wish to call, and must represent as
        // MethodInfo tokens:
        // - void Console.WriteLine(string)
        // - string Console.ReadLine()
        // - int Convert.Int32(string)
        // - void Console.WriteLine(string, object[])

        MethodInfo writeMI = typeof(Console).GetMethod(
            "Write",
            new Type[] { typeof(string) });
        MethodInfo readLineMI = typeof(Console).GetMethod(
            "ReadLine",
            new Type[0]);
        MethodInfo convertInt32MI = typeof(Convert).GetMethod(
            "ToInt32",
            new Type[] { typeof(string) });

        Type[]     wlParams    = new Type[] { typeof(string), typeof(object[]) };
        MethodInfo writeLineMI = typeof(Console).GetMethod(
            "WriteLine",
            wlParams);

        // Although we could just refer to the local variables by
        // index (short ints for Ldloc/Stloc, bytes for LdLoc_S/Stloc_S),
        // this time, we'll use LocalBuilders for clarity and to
        // demonstrate their usage and syntax.

        LocalBuilder x1LB         = pmIL.DeclareLocal(typeof(int));
        LocalBuilder y1LB         = pmIL.DeclareLocal(typeof(int));
        LocalBuilder x2LB         = pmIL.DeclareLocal(typeof(int));
        LocalBuilder y2LB         = pmIL.DeclareLocal(typeof(int));
        LocalBuilder point1LB     = pmIL.DeclareLocal(myTypeBldr);
        LocalBuilder point2LB     = pmIL.DeclareLocal(myTypeBldr);
        LocalBuilder tempObjArrLB = pmIL.DeclareLocal(typeof(object[]));

        pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 1: ");
        pmIL.EmitCall(OpCodes.Call, writeMI, null);
        pmIL.EmitCall(OpCodes.Call, readLineMI, null);
        pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
        pmIL.Emit(OpCodes.Stloc, x1LB);

        pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 1: ");
        pmIL.EmitCall(OpCodes.Call, writeMI, null);
        pmIL.EmitCall(OpCodes.Call, readLineMI, null);
        pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
        pmIL.Emit(OpCodes.Stloc, y1LB);

        pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 2: ");
        pmIL.EmitCall(OpCodes.Call, writeMI, null);
        pmIL.EmitCall(OpCodes.Call, readLineMI, null);
        pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
        pmIL.Emit(OpCodes.Stloc, x2LB);

        pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 2: ");
        pmIL.EmitCall(OpCodes.Call, writeMI, null);
        pmIL.EmitCall(OpCodes.Call, readLineMI, null);
        pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
        pmIL.Emit(OpCodes.Stloc, y2LB);

        pmIL.Emit(OpCodes.Ldloc, x1LB);
        pmIL.Emit(OpCodes.Ldloc, y1LB);
        pmIL.Emit(OpCodes.Newobj, pointCtor);
        pmIL.Emit(OpCodes.Stloc, point1LB);

        pmIL.Emit(OpCodes.Ldloc, x2LB);
        pmIL.Emit(OpCodes.Ldloc, y2LB);
        pmIL.Emit(OpCodes.Newobj, pointCtor);
        pmIL.Emit(OpCodes.Stloc, point2LB);

        pmIL.Emit(OpCodes.Ldstr, "({0}, {1}) . ({2}, {3}) = {4}.");
        pmIL.Emit(OpCodes.Ldc_I4_5);
        pmIL.Emit(OpCodes.Newarr, typeof(Object));
        pmIL.Emit(OpCodes.Stloc, tempObjArrLB);

        pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
        pmIL.Emit(OpCodes.Ldc_I4_0);
        pmIL.Emit(OpCodes.Ldloc, x1LB);
        pmIL.Emit(OpCodes.Box, typeof(int));
        pmIL.Emit(OpCodes.Stelem_Ref);

        pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
        pmIL.Emit(OpCodes.Ldc_I4_1);
        pmIL.Emit(OpCodes.Ldloc, y1LB);
        pmIL.Emit(OpCodes.Box, typeof(int));
        pmIL.Emit(OpCodes.Stelem_Ref);

        pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
        pmIL.Emit(OpCodes.Ldc_I4_2);
        pmIL.Emit(OpCodes.Ldloc, x2LB);
        pmIL.Emit(OpCodes.Box, typeof(int));
        pmIL.Emit(OpCodes.Stelem_Ref);

        pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
        pmIL.Emit(OpCodes.Ldc_I4_3);
        pmIL.Emit(OpCodes.Ldloc, y2LB);
        pmIL.Emit(OpCodes.Box, typeof(int));
        pmIL.Emit(OpCodes.Stelem_Ref);

        pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
        pmIL.Emit(OpCodes.Ldc_I4_4);
        pmIL.Emit(OpCodes.Ldloc, point1LB);
        pmIL.Emit(OpCodes.Ldloc, point2LB);
        pmIL.EmitCall(OpCodes.Callvirt, pointDPBldr, null);

        pmIL.Emit(OpCodes.Box, typeof(int));
        pmIL.Emit(OpCodes.Stelem_Ref);
        pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
        pmIL.EmitCall(OpCodes.Call, writeLineMI, null);

        pmIL.Emit(OpCodes.Ret);

        Console.WriteLine("PointMain (entry point) built.");

        pointType = myTypeBldr.CreateType();

        Console.WriteLine("Type completed.");

        myAsmBldr.SetEntryPoint(pointMainBldr);

        myAsmBldr.Save(asmFileName);

        Console.WriteLine("Assembly saved as '{0}'.", asmFileName);
        Console.WriteLine("Type '{0}' at the prompt to run your new " +
                          "dynamically generated dot product calculator.",
                          asmFileName);

        // After execution, this program will have generated and written to disk,
        // in the directory you executed it from, a program named
        // <name_you_entered_here>.exe. You can run it by typing
        // the name you gave it during execution, in the same directory where
        // you executed this program.

        return(pointType);
    }
Exemplo n.º 19
0
        public InterfaceImplementor(Handler handler)
        {
            Type   intf    = typeof(TInterface);
            string intname = intf.Name;

            if (!intf.IsInterface)
            {
                throw new ArgumentException("TInterface is not an interface");
            }

            AssemblyName asmName = new AssemblyName();

            asmName.Name = intname + "Implementation";

            AppDomain       ad = AppDomain.CurrentDomain;
            AssemblyBuilder ab = ad.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
            ModuleBuilder   mb = ab.DefineDynamicModule(asmName.Name, asmName.Name + ".dll");
            TypeBuilder     tb = mb.DefineType(
                asmName.Name + "Impl",
                TypeAttributes.Class,
                typeof(MarshalByRefObject),
                new Type[] { intf });

            FieldBuilder methodHandler = tb.DefineField(
                "handler",
                typeof(Handler),
                FieldAttributes.Private);

            ConstructorInfo    baseConstructorInfo = typeof(object).GetConstructor(new Type[0]);
            ConstructorBuilder cb = tb.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                new Type[] { typeof(Handler) });

            // Make the constructor
            ILGenerator gen = cb.GetILGenerator();


            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Call, baseConstructorInfo);

            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Stfld, methodHandler);
            gen.Emit(OpCodes.Ret);


            foreach (MethodInfo mi in intf.GetMethods())
            {
                ParameterInfo[] pis = mi.GetParameters();

                MethodBuilder method = tb.DefineMethod(
                    mi.Name,
                    MethodAttributes.Public |
                    MethodAttributes.Virtual |
                    MethodAttributes.Final |
                    MethodAttributes.HideBySig |
                    MethodAttributes.NewSlot,
                    CallingConventions.Standard,
                    mi.ReturnType,
                    ArrayUtils.ConvertAll(pis, x => x.ParameterType));



                ILGenerator mgen = method.GetILGenerator();

                LocalBuilder lb = mgen.DeclareLocal(typeof(object[]));


                mgen.Emit(OpCodes.Nop);
                mgen.Emit(OpCodes.Ldarg_0);
                mgen.Emit(OpCodes.Ldfld, methodHandler);
                mgen.Emit(OpCodes.Ldstr, mi.Name);


                // Make the object array

                if (pis.Length == 0)
                {
                    mgen.Emit(OpCodes.Ldc_I4_0);
                }
                else if (pis.Length == 1)
                {
                    mgen.Emit(OpCodes.Ldc_I4_1);
                }
                else if (pis.Length == 2)
                {
                    mgen.Emit(OpCodes.Ldc_I4_2);
                }
                else if (pis.Length == 3)
                {
                    mgen.Emit(OpCodes.Ldc_I4_3);
                }
                else if (pis.Length == 4)
                {
                    mgen.Emit(OpCodes.Ldc_I4_4);
                }
                else if (pis.Length == 5)
                {
                    mgen.Emit(OpCodes.Ldc_I4_5);
                }
                else if (pis.Length == 6)
                {
                    mgen.Emit(OpCodes.Ldc_I4_6);
                }
                else if (pis.Length == 7)
                {
                    mgen.Emit(OpCodes.Ldc_I4_7);
                }
                else if (pis.Length == 8)
                {
                    mgen.Emit(OpCodes.Ldc_I4_8);
                }
                else
                {
                    mgen.Emit(OpCodes.Ldc_I4, pis.Length);
                }
                mgen.Emit(OpCodes.Newarr, typeof(object));
                mgen.Emit(OpCodes.Stloc_0);

                for (int i = 0; i < pis.Length; i++)
                {
                    // Load the object array
                    mgen.Emit(OpCodes.Ldloc_0);

                    if (i == 0)
                    {
                        mgen.Emit(OpCodes.Ldc_I4_0);
                        mgen.Emit(OpCodes.Ldarg_1);
                    }
                    else
                    {
                        mgen.Emit(OpCodes.Ldc_I4, i);
                        mgen.Emit(OpCodes.Ldarg, i + 1);
                    }

                    if (pis[i].ParameterType.IsValueType)
                    {
                        mgen.Emit(OpCodes.Box, pis[i].ParameterType);
                    }
                    mgen.Emit(OpCodes.Stelem_Ref);
                }

                mgen.Emit(OpCodes.Ldloc_0);

                mgen.EmitCall(
                    OpCodes.Callvirt,
                    typeof(Handler).GetMethod("Invoke"),
                    new Type[] { typeof(object) });

                if (mi.ReturnType == typeof(void))
                {
                    mgen.Emit(OpCodes.Pop);
                }

                mgen.Emit(OpCodes.Ret);

                tb.DefineMethodOverride(method, mi);
            }

            Type t = tb.CreateType();

            ab.Save(asmName.Name + ".dll");

            Interface = (TInterface)Activator.CreateInstance(t, handler);
        }
        /*
         * Generates an implementation of klass, if it is an interface, or
         * a subclass of klass that delegates its virtual methods to a Lua table.
         */
        public void GenerateClass(Type klass, out Type newType, out Type[][] returnTypes)
        {
            string typeName;

            lock (this)
            {
                typeName = "LuaGeneratedClass" + luaClassNumber;
                luaClassNumber++;
            }
            TypeBuilder myType;

            // Define a public class in the assembly, called typeName
            if (klass.IsInterface)
            {
                myType = newModule.DefineType(typeName, TypeAttributes.Public, typeof(object), new Type[] { klass, typeof(ILuaGeneratedType) });
            }
            else
            {
                myType = newModule.DefineType(typeName, TypeAttributes.Public, klass, new Type[] { typeof(ILuaGeneratedType) });
            }
            // Field that stores the Lua table
            FieldBuilder luaTableField = myType.DefineField("__luaInterface_luaTable", typeof(LuaTable), FieldAttributes.Public);
            // Field that stores the return types array
            FieldBuilder returnTypesField = myType.DefineField("__luaInterface_returnTypes", typeof(Type[][]), FieldAttributes.Public);
            // Generates the constructor for the new type, it takes a Lua table and an array
            // of return types and stores them in the respective fields
            ConstructorBuilder constructor =
                myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(LuaTable), typeof(Type[][]) });
            ILGenerator generator = constructor.GetILGenerator();

            generator.Emit(OpCodes.Ldarg_0);
            if (klass.IsInterface)
            {
                generator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
            }
            else
            {
                generator.Emit(OpCodes.Call, klass.GetConstructor(Type.EmptyTypes));
            }
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_1);
            generator.Emit(OpCodes.Stfld, luaTableField);
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Stfld, returnTypesField);
            generator.Emit(OpCodes.Ret);
            // Generates overriden versions of the klass' public virtual methods
            MethodInfo[] classMethods = klass.GetMethods();
            returnTypes = new Type[classMethods.Length][];
            int i = 0;

            foreach (MethodInfo method in classMethods)
            {
                if (klass.IsInterface)
                {
                    GenerateMethod(myType, method,
                                   MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot,
                                   i, luaTableField, returnTypesField, false, out returnTypes[i]);
                    i++;
                }
                else
                {
                    if (!method.IsPrivate && !method.IsFinal && method.IsVirtual)
                    {
                        GenerateMethod(myType, method, (method.Attributes | MethodAttributes.NewSlot) ^ MethodAttributes.NewSlot, i,
                                       luaTableField, returnTypesField, true, out returnTypes[i]);
                        i++;
                    }
                }
            }
            // Generates an implementation of the __luaInterface_getLuaTable method
            MethodBuilder returnTableMethod = myType.DefineMethod("__luaInterface_getLuaTable",
                                                                  MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                                                                  typeof(LuaTable), new Type[0]);

            myType.DefineMethodOverride(returnTableMethod, typeof(ILuaGeneratedType).GetMethod("__luaInterface_getLuaTable"));
            generator = returnTableMethod.GetILGenerator();
            generator.Emit(OpCodes.Ldfld, luaTableField);
            generator.Emit(OpCodes.Ret);
            // Creates the type
            newType = myType.CreateType();
        }
Exemplo n.º 21
0
        public static IComparer <T> Compile <T>(AssemblyEmitter assembly, Type objectType, Property[] props)
        {
            TypeBuilder typeBuilder = assembly.DefineType(
                "__distinct",
                TypeAttributes.Public,
                typeof(object)
                );

            #region Constructor

            {
                ConstructorBuilder ctor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes
                    );

                ILGenerator il = ctor.GetILGenerator();

                // : base()
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, typeof(T).GetConstructor(Type.EmptyTypes) ??
                        throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}"));

                // return;
                il.Emit(OpCodes.Ret);
            }

            #endregion

            #region IComparer

            typeBuilder.AddInterfaceImplementation(typeof(IComparer <T>));

            MethodBuilder compareMethod;

            #region Compare

            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Compare",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new[] { typeof(T), typeof(T) });

                LocalBuilder a = emitter.CreateLocal(objectType);
                LocalBuilder b = emitter.CreateLocal(objectType);

                LocalBuilder v = emitter.CreateLocal(typeof(int));

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(a);

                emitter.LoadArgument(2);
                emitter.CastAs(objectType);
                emitter.StoreLocal(b);

                emitter.Load(0);
                emitter.StoreLocal(v);

                Label end = emitter.CreateLabel();

                for (int i = 0; i < props.Length; ++i)
                {
                    if (i > 0)
                    {
                        emitter.LoadLocal(v);
                        emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
                    }

                    Property prop = props[i];

                    emitter.LoadLocal(a);
                    emitter.Chain(prop);

                    bool couldCompare =
                        emitter.CompareTo(1, delegate
                    {
                        emitter.LoadLocal(b);
                        emitter.Chain(prop);
                    });

                    if (!couldCompare)
                    {
                        throw new InvalidOperationException("Property is not comparable.");
                    }

                    emitter.StoreLocal(v);
                }

                emitter.MarkLabel(end);

                emitter.LoadLocal(v);
                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IComparer <T>).GetMethod(
                        "Compare",
                        new[]
                {
                    typeof(T),
                    typeof(T)
                }
                        ) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}")
                    );

                compareMethod = emitter.Method;
            }

            #endregion

            #endregion

            #region IEqualityComparer

            typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer <T>));

            #region Equals

            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Equals",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(bool),
                    /* params */ new[] { typeof(T), typeof(T) });

                emitter.Generator.Emit(OpCodes.Ldarg_0);
                emitter.Generator.Emit(OpCodes.Ldarg_1);
                emitter.Generator.Emit(OpCodes.Ldarg_2);

                emitter.Generator.Emit(OpCodes.Call, compareMethod);

                emitter.Generator.Emit(OpCodes.Ldc_I4_0);

                emitter.Generator.Emit(OpCodes.Ceq);

                emitter.Generator.Emit(OpCodes.Ret);

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer <T>).GetMethod(
                        "Equals",
                        new[]
                {
                    typeof(T),
                    typeof(T)
                }
                        ) ?? throw new Exception($"No Equals method found for type {typeof(T).FullName}")
                    );
            }

            #endregion

            #region GetHashCode

            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "GetHashCode",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new[] { typeof(T) });

                LocalBuilder obj = emitter.CreateLocal(objectType);

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(obj);

                for (int i = 0; i < props.Length; ++i)
                {
                    Property prop = props[i];

                    emitter.LoadLocal(obj);
                    emitter.Chain(prop);

                    Type active = emitter.Active;

                    MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);

                    getHashCode ??= typeof(T).GetMethod("GetHashCode", Type.EmptyTypes);

                    if (active != typeof(int))
                    {
                        if (!active.IsValueType)
                        {
                            LocalBuilder value = emitter.AcquireTemp(active);

                            Label valueNotNull = emitter.CreateLabel();
                            Label done         = emitter.CreateLabel();

                            emitter.StoreLocal(value);
                            emitter.LoadLocal(value);

                            emitter.BranchIfTrue(valueNotNull);

                            emitter.Load(0);
                            emitter.Pop(typeof(int));

                            emitter.Branch(done);

                            emitter.MarkLabel(valueNotNull);

                            emitter.LoadLocal(value);
                            emitter.Call(getHashCode);

                            emitter.ReleaseTemp(value);

                            emitter.MarkLabel(done);
                        }
                        else
                        {
                            emitter.Call(getHashCode);
                        }
                    }

                    if (i > 0)
                    {
                        emitter.Xor();
                    }
                }

                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer <T>).GetMethod(
                        "GetHashCode",
                        new[]
                {
                    typeof(T)
                }
                        ) ?? throw new Exception($"No GetHashCode method found for type {typeof(T).FullName}")
                    );
            }

            #endregion

            #endregion

            Type comparerType = typeBuilder.CreateType();

            return((IComparer <T>)ActivatorUtil.CreateInstance(comparerType));
        }
Exemplo n.º 22
0
        private Type CreateType(IProxyInvocationHandler handler, Type[] interfaces, string dynamicTypeName)
        {
            Type retVal = null;

            if (handler != null && interfaces != null)
            {
                Type objType     = typeof(System.Object);
                Type handlerType = typeof(IProxyInvocationHandler);

                AppDomain    domain       = Thread.GetDomain();
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name    = ASSEMBLY_NAME;
                assemblyName.Version = new Version(1, 0, 0, 0);

                // create a new assembly for this proxy, one that isn't presisted on the file system
                AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(
                    assemblyName, AssemblyBuilderAccess.Run);
                // assemblyName, AssemblyBuilderAccess.RunAndSave,".");  // to save it to the disk

                // create a new module for this proxy
                ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(MODULE_NAME);

                // Set the class to be public and sealed
                TypeAttributes typeAttributes =
                    TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;

                // Gather up the proxy information and create a new type builder.  One that
                // inherits from Object and implements the interface passed in
                TypeBuilder typeBuilder = moduleBuilder.DefineType(
                    dynamicTypeName, typeAttributes, objType, interfaces);

                // Define a member variable to hold the delegate
                FieldBuilder handlerField = typeBuilder.DefineField(
                    HANDLER_NAME, handlerType, FieldAttributes.Private);


                // build a constructor that takes the delegate object as the only argument
                //ConstructorInfo defaultObjConstructor = objType.GetConstructor( new Type[0] );
                ConstructorInfo    superConstructor    = objType.GetConstructor(new Type[0]);
                ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });

                #region ( "Constructor IL Code" )
                ILGenerator constructorIL = delegateConstructor.GetILGenerator();

                // Load "this"
                constructorIL.Emit(OpCodes.Ldarg_0);
                // Load first constructor parameter
                constructorIL.Emit(OpCodes.Ldarg_1);
                // Set the first parameter into the handler field
                constructorIL.Emit(OpCodes.Stfld, handlerField);
                // Load "this"
                constructorIL.Emit(OpCodes.Ldarg_0);
                // Call the super constructor
                constructorIL.Emit(OpCodes.Call, superConstructor);
                // Constructor return
                constructorIL.Emit(OpCodes.Ret);
                #endregion

                // for every method that the interfaces define, build a corresponding
                // method in the dynamic type that calls the handlers invoke method.
                foreach (Type interfaceType in interfaces)
                {
                    GenerateMethod(interfaceType, handlerField, typeBuilder);
                }

                retVal = typeBuilder.CreateType();

                // assemblyBuilder.Save(dynamicTypeName + ".dll");
            }

            return(retVal);
        }
Exemplo n.º 23
0
        private void DefineConstructors()
        {
            BindingFlags    bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            ConstructorInfo emptyCtor    = _tb.BaseType.GetConstructor(bindingFlags, null, Type.EmptyTypes, null);
            ConstructorInfo classArgCtor = null;

            bool deserializerFound = false;

            foreach (var baseCtor in _tb.BaseType.GetConstructors(bindingFlags))
            {
                if (!baseCtor.IsPublic && !baseCtor.IsFamily)
                {
                    continue;
                }

                int         oldLength = baseCtor.GetParameters().Length;
                List <Type> newParams = new List <Type>(oldLength + 1);
                foreach (var param in baseCtor.GetParameters())
                {
                    newParams.Add(param.ParameterType);
                }

                int  offset         = 1;
                bool isDeserializer = false;
                if (oldLength > 0 && newParams[0] == typeof(RubyClass))
                {
                    // Build a simple pass-through constructor
                    offset = 0;
#if !SILVERLIGHT
                }
                else if (oldLength == 2 && newParams[0] == typeof(SerializationInfo) && newParams[1] == typeof(StreamingContext))
                {
                    // Build a deserializer
                    deserializerFound = true;
                    isDeserializer    = true;
                    offset            = 0;
#endif
                }
                else
                {
                    // Special-case for Exception
                    if (_tb.IsSubclassOf(typeof(Exception)) && IsAvailable(emptyCtor))
                    {
                        if (oldLength == 0)
                        {
                            // Skip this constructor; it would conflict with the one we're going to build next
                            continue;
                        }
                        else if (oldLength == 1 && newParams[0] == typeof(string))
                        {
                            // Special case exceptions to improve interop. Ruby's default message for an exception is the name of the exception class.
                            BuildExceptionConstructor(baseCtor);
                        }
                    }

                    // Add RubyClass to the head of the parameter list
                    newParams.Insert(0, typeof(RubyClass));
                }

                // Build a new constructor based on this base class ctor
                ConstructorBuilder cb = _tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, newParams.ToArray());
                ILGen il = new ILGen(cb.GetILGenerator());
                il.EmitLoadArg(0);
                for (int i = 1; i < newParams.Count; i++)
                {
                    il.EmitLoadArg(i + offset);
                }
                il.Emit(OpCodes.Call, baseCtor);
                if (!isDeserializer)
                {
                    // ctor(RubyClass! class, ...) : ... { this._class = class; }
                    il.EmitLoadArg(0);
                    il.EmitLoadArg(1);
                    il.EmitFieldSet(_classField);
                }
                else
                {
                    // ctor(SerializationInfo! info, StreamingContext! context) : base {
                    //   RubyOps.DeserializeObject(out this._instanceData, out this._class, info);
                    // }
                    il.EmitLoadArg(0);
                    il.EmitFieldAddress(_instanceDataField);
                    il.EmitLoadArg(0);
                    il.EmitFieldAddress(_classField);
                    il.EmitLoadArg(1);
                    il.EmitCall(typeof(RubyOps).GetMethod("DeserializeObject"));
                }
                il.Emit(OpCodes.Ret);

                if (oldLength == 0)
                {
                    classArgCtor = cb;
                }
            }
#if !SILVERLIGHT
            if (classArgCtor != null && !deserializerFound)
            {
                // We didn't previously find a deserialization constructor.  If we can, build one now.
                BuildDeserializationConstructor(classArgCtor);
            }
#endif
        }
Exemplo n.º 24
0
        private static Type CreateRowType(IDictionary <string, Type> properties)
        {
            string[] propertyNames = properties.Keys.ToArray();
            Type[]   propertyTypes = properties.Values.ToArray();

            TypeBuilder typeBuilder;

            lock (moduleBuilderLock)
            {
                typeCount++;
                typeBuilder =
                    moduleBuilder.DefineType(
                        string.Format("DataRow{0}", typeCount),
                        TypeAttributes.Public,
                        // Derive from object
                        typeof(DataRow),
                        // No interfaces
                        Type.EmptyTypes);
            }

            bool isLarge = LargeDataRowAttribute.LargePropertyCount <= properties.Count;

            #region LargeDataRowAttribute

            if (isLarge)
            {
                ConstructorInfo largeDataRowAttrCtor =
                    typeof(LargeDataRowAttribute).GetConstructor(
                        BindingFlags.Instance | BindingFlags.Public,
                        null,
                        Type.EmptyTypes,
                        null);

                typeBuilder.SetCustomAttribute(
                    new CustomAttributeBuilder(largeDataRowAttrCtor, new object[0]));
            }

            #endregion

            #region Properties and fields

            FieldBuilder[] fields = new FieldBuilder[properties.Count];

            for (int i = 0; i < properties.Count; i++)
            {
                string name = propertyNames[i];
                Type   type = propertyTypes[i];

                FieldBuilder field = CreateFieldAndProperty(typeBuilder, name, i, type);

                fields[i] = field;
            }

            #endregion

            #region Constructor

            ConstructorBuilder ctorBuilder =
                typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    isLarge ?
                    new Type[] { typeof(object[]) } :
                    propertyTypes);

            if (isLarge)
            {
                ctorBuilder.DefineParameter(0, ParameterAttributes.None, "args");
            }
            else
            {
                for (int i = 0; i < propertyNames.Length; i++)
                {
                    ctorBuilder.DefineParameter(
                        i,
                        ParameterAttributes.None,
                        propertyNames[i]);
                }
            }

            GenerateConstructorIL(ctorBuilder.GetILGenerator(), fields, isLarge);

            #endregion

            #region GetHashCode

            MethodBuilder getHashCodeBuilder =
                typeBuilder.DefineMethod(
                    "GetHashCode",
                    MethodAttributes.Public |
                    MethodAttributes.Virtual |
                    MethodAttributes.HideBySig,
                    null,
                    Type.EmptyTypes);

            getHashCodeBuilder.SetReturnType(typeof(int));

            GenerateGetHashcodeIL(getHashCodeBuilder.GetILGenerator(), fields);

            #endregion

            #region Equals

            MethodBuilder equalsBuilder =
                typeBuilder.DefineMethod(
                    "Equals",
                    MethodAttributes.Public |
                    MethodAttributes.Virtual |
                    MethodAttributes.HideBySig,
                    null,
                    Type.EmptyTypes);

            equalsBuilder.SetParameters(new Type[] { typeof(object) });
            equalsBuilder.SetReturnType(typeof(bool));
            GenerateEqualsIL(equalsBuilder.GetILGenerator(), fields, typeBuilder);

            #endregion

            #region GetValue

            MethodBuilder getValueBuilder =
                typeBuilder.DefineMethod(
                    GetValueNameMethod.Name,
                    MethodAttributes.Public |
                    MethodAttributes.Virtual |
                    MethodAttributes.HideBySig,
                    null,
                    Type.EmptyTypes);

            getValueBuilder.SetParameters(new Type[] { typeof(int) });
            getValueBuilder.SetReturnType(typeof(object));
            GenerateGetValueIL(getValueBuilder.GetILGenerator(), fields, typeBuilder);

            #endregion

            return(typeBuilder.CreateType());
        }
        public static T Import <T>(INativeLibImporter importer, string libName, string version, bool suppressUnload) where T : class
        {
            Console.WriteLine("Import: " + $"{libName}-{version}");

            //var subdir = GetArchName(RuntimeInformation.ProcessArchitecture);
            var runtimeId = GetRuntimeId(RuntimeInformation.ProcessArchitecture);

            var    assemblyName    = new AssemblyName("DynamicLink");
            var    assemblyBuilder = CurrentFramework.DefineDynamicAssembly(assemblyName, System.Reflection.Emit.AssemblyBuilderAccess.Run);
            var    moduleBuilder   = assemblyBuilder.DefineDynamicModule("DynLinkModule");
            string typeName        = typeof(T).Name + "_impl";
            var    typeBuilder     = moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, typeof(T));

            FieldBuilder field_importer      = typeBuilder.DefineField("importer", typeof(INativeLibImporter), FieldAttributes.Private | FieldAttributes.InitOnly);
            FieldBuilder field_libraryHandle = typeBuilder.DefineField("libraryHandle", typeof(IntPtr), FieldAttributes.Private | FieldAttributes.InitOnly);

            var methods = typeof(T).GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.IsAbstract && !m.IsGenericMethod).ToArray();

            // Define delegate types for each of the method signatures
            var delegateMap = new Dictionary <string, Type>();

            foreach (var method in methods)
            {
                var sig = GetMethodSig(method);
                if (delegateMap.ContainsKey(sig))
                {
                    continue;
                }
                var delegateTypeInfo = CreateDelegateType(moduleBuilder, method);
                delegateMap.Add(sig, delegateTypeInfo.AsType());
            }

            // Define one field for each method to hold a delegate
            var delegates = methods.Select(m => new {
                MethodInfo   = m,
                DelegateType = delegateMap[GetMethodSig(m)],
            }).ToArray();
            var delegateFields = delegates.Select((d, i) => typeBuilder.DefineField($"{d.MethodInfo.Name}_func_{i}", d.DelegateType, FieldAttributes.Private)).ToArray();

            // Create the constructor which will initialize the importer and library handle
            // and also use the importer to populate each of the delegate fields
            ConstructorBuilder constructor = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(INativeLibImporter), typeof(IntPtr) });

            {
                var         baseConstructor = typeof(T).GetTypeInfo().GetConstructors().Where(con => con.GetParameters().Length == 0).First();
                ILGenerator il = constructor.GetILGenerator();

                // Call base constructor
                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Call, baseConstructor);

                // Store importer field
                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Ldarg_1); // importer
                il.Emit(OpCodes.Stfld, field_importer);

                // Load and store library handle
                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Ldarg_2); // library handle
                il.Emit(OpCodes.Stfld, field_libraryHandle);

                var getDelegateMethod = typeof(INativeLibImporter).GetTypeInfo().GetMethod("GetDelegate");
                // Initialize each delegate field
                for (int i = 0; i < delegateFields.Length; i++)
                {
                    var delegateType = delegates[i].DelegateType;

                    il.Emit(OpCodes.Ldarg_0);                                                                // this

                    il.Emit(OpCodes.Ldarg_1);                                                                // importer
                    il.Emit(OpCodes.Ldarg_0);                                                                // this
                    il.Emit(OpCodes.Ldfld, field_libraryHandle);
                    il.Emit(OpCodes.Ldstr, delegates[i].MethodInfo.Name);                                    // use method name from original class as entry point
                    il.Emit(OpCodes.Ldtoken, delegateType);                                                  // the delegate type
                    il.Emit(OpCodes.Call, typeof(System.Type).GetTypeInfo().GetMethod("GetTypeFromHandle")); // typeof()
                    il.Emit(OpCodes.Callvirt, getDelegateMethod);                                            // importer.GetDelegate()
                    il.Emit(OpCodes.Isinst, delegateType);                                                   // as <delegate type>
                    il.Emit(OpCodes.Stfld, delegateFields[i]);
                }

                // End of constructor
                il.Emit(OpCodes.Ret);
            }

            // Create destructor
            var destructor = typeBuilder.DefineMethod("Finalize", MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig);
            {
                var baseDestructor = typeof(T).GetTypeInfo().GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance);
                var il             = destructor.GetILGenerator();
                var end            = il.DefineLabel();

                il.BeginExceptionBlock();
                if (!suppressUnload)
                {
                    il.Emit(OpCodes.Ldarg_0);                                                                     // this
                    il.Emit(OpCodes.Ldfld, field_importer);                                                       // .importer
                    il.Emit(OpCodes.Ldarg_0);                                                                     // this
                    il.Emit(OpCodes.Ldfld, field_libraryHandle);                                                  // .libraryHandle
                    il.Emit(OpCodes.Callvirt, typeof(INativeLibImporter).GetTypeInfo().GetMethod("FreeLibrary")); // INativeLibImporter::FreeLibrary()
                }
                //il.Emit(OpCodes.Leave, end);
                il.BeginFinallyBlock();
                il.Emit(OpCodes.Ldarg_0);              // this
                il.Emit(OpCodes.Call, baseDestructor); // object::Finalize()
                //il.Emit(OpCodes.Endfinally);
                il.EndExceptionBlock();
                il.MarkLabel(end);
                il.Emit(OpCodes.Ret);
            }

            var nativeFunctionMissingExceptionConstructor = typeof(NativeFunctionMissingException).GetTypeInfo().GetConstructor(new[] { typeof(string) });

            // Now override each method from the base class
            for (int i = 0; i < delegateFields.Length; i++)
            {
                var baseMethod = delegates[i].MethodInfo;
                var args       = baseMethod.GetParameters();
                var omethod    = typeBuilder.DefineMethod(
                    baseMethod.Name,
                    (baseMethod.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot)) | MethodAttributes.Virtual,
                    baseMethod.CallingConvention,
                    baseMethod.ReturnType,
                    args.Select(arg => arg.ParameterType).ToArray()
                    );
                var il = omethod.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);                  // this
                il.Emit(OpCodes.Ldfld, delegateFields[i]); // {field}
                il.Emit(OpCodes.Dup);
                var error = il.DefineLabel();
                il.Emit(OpCodes.Brfalse_S, error);
                if (args.Length >= 1)
                {
                    il.Emit(OpCodes.Ldarg_1);
                }
                if (args.Length >= 2)
                {
                    il.Emit(OpCodes.Ldarg_2);
                }
                if (args.Length >= 3)
                {
                    il.Emit(OpCodes.Ldarg_3);
                }
                for (short argNum = 4; argNum <= args.Length; argNum++)
                {
                    il.Emit(OpCodes.Ldarg_S, argNum);
                }
                il.Emit(OpCodes.Tailcall);
                il.Emit(OpCodes.Callvirt, delegates[i].DelegateType.GetTypeInfo().GetMethod("Invoke"));
                il.Emit(OpCodes.Ret);
                il.MarkLabel(error);
                il.Emit(OpCodes.Ldstr, baseMethod.ToString());
                il.Emit(OpCodes.Newobj, nativeFunctionMissingExceptionConstructor);
                il.Emit(OpCodes.Throw);
            }

            var type = typeBuilder.CreateTypeInfo();

            var versionParts = version.Split('.');

            //var names = versionParts.Select((p, i) => libName + "-" + string.Join(".", versionParts.Take(i + 1)))
            //    .Reverse()
            //    .Concat(Enumerable.Repeat(libName, 1));

            // Skip looking for versions, only lib with static name.
            var names = new[] { libName };

            // try to load locally
            var paths = new[]
            {
                Path.Combine("runtimes", runtimeId, "native"),
                //Path.Combine("native", subdir),
                //"native",
                //subdir,
                "",
            };

            Console.WriteLine("paths: " + string.Join(':', paths));

            var basePaths = new string[] {
                Directory.GetCurrentDirectory(),
                Path.GetDirectoryName(UriToPath(AppContext.BaseDirectory)),
                // Path.GetDirectoryName(UriToPath(Transitional.CurrentFramework.GetBaseDirectory())),
                Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location),
                // Path.GetDirectoryName(typeof(PosixImporter).GetTypeInfo().Assembly.Location),
            };

            Console.WriteLine("basePaths: " + string.Join(':', basePaths));

            var search = basePaths
                         .Where(p => p != null)
                         .Distinct()
                         .SelectMany(basePath =>
                                     paths.SelectMany(path => names.Select(n => Path.Combine(basePath, path, importer.Translate(n))))
                                     .Concat(names.Select(n => importer.Translate(n)))
                                     )
                         .Select(path => new SearchPath {
                Path = path
            })
                         .ToArray();

            foreach (var spec in search)
            {
                var    construct = type.GetConstructor(new Type[] { typeof(INativeLibImporter), typeof(IntPtr) });
                IntPtr lib       = IntPtr.Zero;
                try
                {
                    Console.WriteLine("LoadLibrary: " + spec.Path);

                    lib = importer.LoadLibrary(spec.Path);
                    if (lib == IntPtr.Zero)
                    {
                        throw new NativeLoadException("LoadLibrary returned 0", null);
                    }
                }
                catch (TargetInvocationException tie)
                {
                    spec.Error = tie.InnerException;

                    Console.WriteLine("TargetInvocationException: " + spec.Error.Message);

                    continue;
                }
                catch (Exception e)
                {
                    spec.Error = e;

                    Console.WriteLine("Exception: " + spec.Error.Message);

                    continue;
                }
                var obj = construct.Invoke(new object[] { importer, lib });
                var t   = obj as T;
                return(t);
            }

            throw new NativeLoadException("Unable to locate rocksdb native library, either install it, or use RocksDbNative nuget package\nSearched:\n" + string.Join("\n", search.Select(s => $"{s.Path}: ({s.Error.GetType().Name}) {s.Error.Message}")), null);
        }
Exemplo n.º 26
0
        /// <summary>
        /// Compiles the functions.
        /// </summary>
        /// <remarks><pre>
        /// 20 Dec 2005 - Jeremy Roberts
        /// </pre></remarks>
        protected void compile()
        {
            // Code to set up the object.

            // Create a new AppDomain.
            // Set up assembly.
            //
            //NewAppDomain = System.AppDomain.CreateDomain("NewApplicationDomain");
            //NewAppDomain = appDomain;

            AssemblyName assemblyName = new AssemblyName();

            assemblyName.Name = "EmittedAssembly";
            AssemblyBuilder assembly = Thread.GetDomain().DefineDynamicAssembly(
                //AssemblyBuilder assembly = NewAppDomain.DefineDynamicAssembly(
                assemblyName,
                //AssemblyBuilderAccess.Save);
                AssemblyBuilderAccess.Run);
            //AssemblyBuilderAccess.RunAndSave);

            // Add Dynamic Module
            //
            ModuleBuilder module;

            module = assembly.DefineDynamicModule("EmittedModule");
            TypeBuilder dynamicFunctionClass = module.DefineType(
                "DynamicFunction",
                TypeAttributes.Public,
                typeof(DynamicFunction));

            // Define class constructor
            //
            Type            objType        = Type.GetType("System.Object");
            ConstructorInfo objConstructor = objType.GetConstructor(new Type[0]);

            Type[]             constructorParams = { };
            ConstructorBuilder constructor       = dynamicFunctionClass.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                constructorParams);

            // Emit the class constructor.
            //
            ILGenerator constructorIL = constructor.GetILGenerator();

            constructorIL.Emit(OpCodes.Ldarg_0);
            constructorIL.Emit(OpCodes.Call, objConstructor);
            constructorIL.Emit(OpCodes.Ret);

            // Define "EvaluateD" function.
            //
            Type[]        args        = { typeof(Dictionary <string, double>) };
            MethodBuilder evalMethodD = dynamicFunctionClass.DefineMethod(
                "EvaluateD",
                MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(double),
                args);
            ILGenerator methodILD;

            methodILD = evalMethodD.GetILGenerator();
            emitFunction(this.PostFix, methodILD);

            // Define "EvaluateB" function.
            //
            MethodBuilder evalMethodB = dynamicFunctionClass.DefineMethod(
                "EvaluateB",
                MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(bool),
                args);
            ILGenerator methodILB;

            methodILB = evalMethodB.GetILGenerator();
            emitFunction(this.PostFix, methodILB);

            // Create an object to use.
            //
            Type dt = dynamicFunctionClass.CreateType();

            //assembly.Save("assem.dll");
            //assembly.Save("x.exe");
            //return (function)Activator.CreateInstance(dt, new Object[] { });
            this.dynamicFunction = (DynamicFunction)Activator.CreateInstance(dt, new Object[] { });
        }
Exemplo n.º 27
0
        private static Type GetWrapperTypeNoCache(Type type, bool logHistory)
        {
            if (type.IsSealed)
            {
                throw new ArgumentException("The supplied type must not be sealed.");
            }

            AppDomain       myDomain   = AppDomain.CurrentDomain;
            AssemblyName    myAsmName  = new AssemblyName(type.Assembly.FullName.Remove(type.Assembly.FullName.IndexOf(",")) + ".__PropertyWatcher");
            AssemblyBuilder myAssembly = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);

            var module = myAssembly.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll");

            TypeBuilder typeBuilder = module.DefineType(type.Name, TypeAttributes.Public, type);

            var propertyWatcherType = typeof(PropertyWatcher <>).MakeGenericType(type);

            var propertyWatcherField       = typeBuilder.DefineField(FieldName, propertyWatcherType, FieldAttributes.Public | FieldAttributes.InitOnly);
            var propertyWatcherConstructor = propertyWatcherType.GetConstructor(new[] { typeof(bool) });

            foreach (var oldConstructor in type.GetConstructors())
            {
                Type[] paramTypes = oldConstructor.GetParameters().Select(c => c.ParameterType).ToArray();

                ConstructorBuilder newConstructorMethodBuilder = typeBuilder.DefineConstructor(oldConstructor.Attributes, oldConstructor.CallingConvention, paramTypes);
                ILGenerator        constructorIL = newConstructorMethodBuilder.GetILGenerator();

                constructorIL.Emit(OpCodes.Ldarg_0);

                constructorIL.Emit(logHistory ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
                constructorIL.Emit(OpCodes.Newobj, propertyWatcherConstructor);
                constructorIL.Emit(OpCodes.Stfld, propertyWatcherField);

                constructorIL.Emit(OpCodes.Ldarg_0);

                for (int v = 0; v < paramTypes.Length; v++)
                {
                    constructorIL.Emit(OpCodes.Ldarga_S, v + 1);
                }

                constructorIL.Emit(OpCodes.Call, oldConstructor);

                constructorIL.Emit(OpCodes.Ret);
            }

            var setMethod = propertyWatcherType.GetMethod("Set", new[] { typeof(string), typeof(object) });

            foreach (var prop in type.GetProperties())
            {
                if (prop.CanWrite)
                {
                    var oldSetter = prop.GetSetMethod();

                    if (!oldSetter.IsVirtual)
                    {
                        throw new ArgumentException(string.Format("The property {0} must be made virtual.", prop.Name));
                    }


                    MethodBuilder pSet   = typeBuilder.DefineMethod(oldSetter.Name, oldSetter.Attributes, oldSetter.ReturnType, new Type[] { prop.PropertyType });
                    ILGenerator   pILSet = pSet.GetILGenerator();

                    pILSet.Emit(OpCodes.Ldarg_0);
                    pILSet.Emit(OpCodes.Ldarg_1);
                    pILSet.Emit(OpCodes.Call, oldSetter);

                    pILSet.Emit(OpCodes.Ldarg_0);
                    pILSet.Emit(OpCodes.Ldfld, propertyWatcherField);
                    pILSet.Emit(OpCodes.Ldstr, prop.Name);
                    pILSet.Emit(OpCodes.Ldarg_1);
                    pILSet.Emit(OpCodes.Callvirt, setMethod);
                    pILSet.Emit(OpCodes.Pop);
                    pILSet.Emit(OpCodes.Ret);

                    typeBuilder.DefineMethodOverride(pSet, oldSetter);
                }
            }

            return(typeBuilder.CreateType());
        }
Exemplo n.º 28
0
        private static void ejemplo()
        {
            // An assembly consists of one or more modules, each of which
            // contains zero or more types. This code creates a single-module
            // assembly, the most common case. The module contains one type,
            // named "MyDynamicType", that has a private field, a property
            // that gets and sets the private field, constructors that
            // initialize the private field, and a method that multiplies
            // a user-supplied number by the private field value and returns
            // the result. In C# the type might look like this:

            /*
             * public class MyDynamicType
             * {
             *  private int m_number;
             *
             *  public MyDynamicType() : this(42) {}
             *  public MyDynamicType(int initNumber)
             *  {
             *      m_number = initNumber;
             *  }
             *
             *  public int Number
             *  {
             *      get { return m_number; }
             *      set { m_number = value; }
             *  }
             *
             *  public int MyMethod(int multiplier)
             *  {
             *      return m_number * multiplier;
             *  }
             * }
             */

            AssemblyName    aName = new AssemblyName("DynamicAssemblyExample");
            AssemblyBuilder ab    =
                AppDomain.CurrentDomain.DefineDynamicAssembly(
                    aName,
                    AssemblyBuilderAccess.RunAndSave);

            // For a single-module assembly, the module name is usually
            // the assembly name plus an extension.
            ModuleBuilder mb =
                ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

            TypeBuilder tb = mb.DefineType(
                "MyDynamicType",
                TypeAttributes.Public);

            // Add a private field of type int (Int32).
            FieldBuilder fbNumber = tb.DefineField(
                "m_number",
                typeof(int),
                FieldAttributes.Private);

            // Define a constructor that takes an integer argument and
            // stores it in the private field.
            Type[]             parameterTypes = { typeof(int) };
            ConstructorBuilder ctor1          = tb.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                parameterTypes);

            ILGenerator ctor1IL = ctor1.GetILGenerator();

            // For a constructor, argument zero is a reference to the new
            // instance. Push it on the stack before calling the base
            // class constructor. Specify the default constructor of the
            // base class (System.Object) by passing an empty array of
            // types (Type.EmptyTypes) to GetConstructor.
            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Call,
                         typeof(object).GetConstructor(Type.EmptyTypes));
            // Push the instance on the stack before pushing the argument
            // that is to be assigned to the private field m_number.
            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Ldarg_1);
            ctor1IL.Emit(OpCodes.Stfld, fbNumber);
            ctor1IL.Emit(OpCodes.Ret);

            // Define a default constructor that supplies a default value
            // for the private field. For parameter types, pass the empty
            // array of types or pass null.
            ConstructorBuilder ctor0 = tb.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                Type.EmptyTypes);

            ILGenerator ctor0IL = ctor0.GetILGenerator();

            // For a constructor, argument zero is a reference to the new
            // instance. Push it on the stack before pushing the default
            // value on the stack, then call constructor ctor1.
            ctor0IL.Emit(OpCodes.Ldarg_0);
            ctor0IL.Emit(OpCodes.Ldc_I4_S, 42);
            ctor0IL.Emit(OpCodes.Call, ctor1);
            ctor0IL.Emit(OpCodes.Ret);

            // Define a property named Number that gets and sets the private
            // field.
            //
            // The last argument of DefineProperty is null, because the
            // property has no parameters. (If you don't specify null, you must
            // specify an array of Type objects. For a parameterless property,
            // use the built-in array with no elements: Type.EmptyTypes)
            PropertyBuilder pbNumber = tb.DefineProperty(
                "Number",
                PropertyAttributes.HasDefault,
                typeof(int),
                null);

            // The property "set" and property "get" methods require a special
            // set of attributes.
            MethodAttributes getSetAttr = MethodAttributes.Public |
                                          MethodAttributes.SpecialName | MethodAttributes.HideBySig;

            // Define the "get" accessor method for Number. The method returns
            // an integer and has no arguments. (Note that null could be
            // used instead of Types.EmptyTypes)
            MethodBuilder mbNumberGetAccessor = tb.DefineMethod(
                "get_Number",
                getSetAttr,
                typeof(int),
                Type.EmptyTypes);

            ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();

            // For an instance property, argument zero is the instance. Load the
            // instance, then load the private field and return, leaving the
            // field value on the stack.
            numberGetIL.Emit(OpCodes.Ldarg_0);
            numberGetIL.Emit(OpCodes.Ldfld, fbNumber);
            numberGetIL.Emit(OpCodes.Ret);

            // Define the "set" accessor method for Number, which has no return
            // type and takes one argument of type int (Int32).
            MethodBuilder mbNumberSetAccessor = tb.DefineMethod(
                "set_Number",
                getSetAttr,
                null,
                new Type[] { typeof(int) });

            ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();

            // Load the instance and then the numeric argument, then store the
            // argument in the field.
            numberSetIL.Emit(OpCodes.Ldarg_0);
            numberSetIL.Emit(OpCodes.Ldarg_1);
            numberSetIL.Emit(OpCodes.Stfld, fbNumber);
            numberSetIL.Emit(OpCodes.Ret);

            // Last, map the "get" and "set" accessor methods to the
            // PropertyBuilder. The property is now complete.
            pbNumber.SetGetMethod(mbNumberGetAccessor);
            pbNumber.SetSetMethod(mbNumberSetAccessor);

            // Define a method that accepts an integer argument and returns
            // the product of that integer and the private field m_number. This
            // time, the array of parameter types is created on the fly.
            MethodBuilder meth = tb.DefineMethod(
                "MyMethod",
                MethodAttributes.Public,
                typeof(int),
                new Type[] { typeof(int) });

            ILGenerator methIL = meth.GetILGenerator();

            // To retrieve the private instance field, load the instance it
            // belongs to (argument zero). After loading the field, load the
            // argument one and then multiply. Return from the method with
            // the return value (the product of the two numbers) on the
            // execution stack.
            methIL.Emit(OpCodes.Ldarg_0);
            methIL.Emit(OpCodes.Ldfld, fbNumber);
            methIL.Emit(OpCodes.Ldarg_1);
            methIL.Emit(OpCodes.Mul);
            methIL.Emit(OpCodes.Ret);

            // Finish the type.
            Type t = tb.CreateType();

            // The following line saves the single-module assembly. This
            // requires AssemblyBuilderAccess to include Save. You can now
            // type "ildasm MyDynamicAsm.dll" at the command prompt, and
            // examine the assembly. You can also write a program that has
            // a reference to the assembly, and use the MyDynamicType type.
            //
            ab.Save(aName.Name + ".dll");

            // Because AssemblyBuilderAccess includes Run, the code can be
            // executed immediately. Start by getting reflection objects for
            // the method and the property.
            MethodInfo   mi = t.GetMethod("MyMethod");
            PropertyInfo pi = t.GetProperty("Number");

            // Create an instance of MyDynamicType using the default
            // constructor.
            object o1 = Activator.CreateInstance(t);

            // Display the value of the property, then change it to 127 and
            // display it again. Use null to indicate that the property
            // has no index.
            Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));
            pi.SetValue(o1, 127, null);
            Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));

            // Call MyMethod, passing 22, and display the return value, 22
            // times 127. Arguments must be passed as an array, even when
            // there is only one.
            object[] arguments = { 22 };
            Console.WriteLine("o1.MyMethod(22): {0}",
                              mi.Invoke(o1, arguments));

            // Create an instance of MyDynamicType using the constructor
            // that specifies m_Number. The constructor is identified by
            // matching the types in the argument array. In this case,
            // the argument array is created on the fly. Display the
            // property value.
            object o2 = Activator.CreateInstance(t,
                                                 new object[] { 5280 });

            Console.WriteLine("o2.Number: {0}", pi.GetValue(o2, null));
        }
Exemplo n.º 29
0
        public static Type CreateDbContextType(this ModuleBuilder moduleBuilder, string connectionKey, List <Entry> entrys)
        {
            //Define Type
            string         typeName        = $"{moduleBuilder.Assembly.GetName().Name}.{connectionKey}.Models.{connectionKey}Context";
            var            dbContexttype   = typeof(DbContext);
            Type           listOf          = typeof(DbSet <>);
            TypeAttributes contextTypeAttr = TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit;
            TypeBuilder    typeBuilder     = moduleBuilder.DefineType(typeName, contextTypeAttr, dbContexttype);

            //Define Constructor
            Type               toptionType          = typeof(DbContextOptions <>);
            Type               optionType           = toptionType.MakeGenericType(typeBuilder);
            MethodAttributes   ctormethodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
            ConstructorBuilder ctor1 = typeBuilder.DefineConstructor(
                ctormethodAttributes,
                CallingConventions.Standard, new[] { optionType });
            ILGenerator     ctor0Il    = ctor1.GetILGenerator();
            ConstructorInfo ctormethod = dbContexttype.GetConstructor(new[] { typeof(DbContextOptions) });

            ctor0Il.Emit(OpCodes.Ldarg_0);
            ctor0Il.Emit(OpCodes.Ldarg_1);
            ctor0Il.Emit(OpCodes.Call, ctormethod);
            ctor0Il.Emit(OpCodes.Nop);
            ctor0Il.Emit(OpCodes.Nop);
            ctor0Il.Emit(OpCodes.Ret);

            //Define Property
            foreach (var entry in entrys)
            {
                var          modelTypeName = entry.Type.Name;
                Type         listOfTFirst  = listOf.MakeGenericType(entry.Type);
                FieldBuilder fieldBldr     = typeBuilder.DefineField("_" + modelTypeName.ToLower(),
                                                                     listOfTFirst,
                                                                     FieldAttributes.Private);
                PropertyBuilder propBldr = typeBuilder.DefineProperty(modelTypeName,
                                                                      PropertyAttributes.HasDefault,
                                                                      listOfTFirst,
                                                                      null);
                const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName |
                                                    MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot;
                MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod("get_" + modelTypeName,
                                                                         getSetAttr,
                                                                         listOfTFirst,
                                                                         Type.EmptyTypes);
                ILGenerator getIlGenerator = getPropMthdBldr.GetILGenerator();
                getIlGenerator.Emit(OpCodes.Ldarg_0);
                getIlGenerator.Emit(OpCodes.Ldfld, fieldBldr);
                getIlGenerator.Emit(OpCodes.Ret);
                MethodBuilder setPropMthdBldr = typeBuilder.DefineMethod("set_" + modelTypeName,
                                                                         getSetAttr,
                                                                         null,
                                                                         new[] { listOfTFirst });
                ILGenerator setIlGenerator = setPropMthdBldr.GetILGenerator();
                setIlGenerator.Emit(OpCodes.Ldarg_0);
                setIlGenerator.Emit(OpCodes.Ldarg_1);
                setIlGenerator.Emit(OpCodes.Stfld, fieldBldr);
                setIlGenerator.Emit(OpCodes.Ret);
                propBldr.SetGetMethod(getPropMthdBldr);
                propBldr.SetSetMethod(setPropMthdBldr);
            }

            //Define OnModelCreating
            MethodAttributes omcMthdAttrs =
                MethodAttributes.Family
                | MethodAttributes.Virtual
                | MethodAttributes.HideBySig;
            MethodBuilder omcMthdBldr = typeBuilder.DefineMethod("OnModelCreating",
                                                                 omcMthdAttrs,
                                                                 typeof(void),
                                                                 new[] { typeof(ModelBuilder) });

            ILGenerator omcMthdIlGen = omcMthdBldr.GetILGenerator();
            MethodInfo  entityMthd   = typeof(ModelBuilder).GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(p => p.GetParameters().Count() == 0 && p.Name == "Entity" && p.IsGenericMethod && p.IsVirtual);
            MethodInfo  ToTableMthd  = typeof(RelationalEntityTypeBuilderExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(p => p.Name == "ToTable" && p.GetParameters().Count() == 3 && p.IsGenericMethod);
            MethodInfo  hasKeyMethod = typeof(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder).GetMethod("HasKey");

            omcMthdIlGen.Emit(OpCodes.Nop);
            foreach (var entry in entrys)
            {
                string[] keys        = entry.Table.Columns.Where(p => p.IsPrimaryKey).Select(p => p.ColumnName).ToArray();
                int      keysCount   = keys.Count();
                OpCode   countOpCode = (OpCode)typeof(OpCodes).GetField($"Ldc_I4_{keysCount}").GetValue(null);

                omcMthdIlGen.Emit(OpCodes.Ldarg_1);
                omcMthdIlGen.Emit(OpCodes.Callvirt, entityMthd.MakeGenericMethod(entry.Type));
                omcMthdIlGen.Emit(OpCodes.Ldstr, entry.Table.Name);
                omcMthdIlGen.Emit(OpCodes.Ldstr, entry.Table.Schema);
                omcMthdIlGen.Emit(OpCodes.Call, ToTableMthd.MakeGenericMethod(entry.Type));

                omcMthdIlGen.Emit(countOpCode);
                omcMthdIlGen.Emit(OpCodes.Newarr, typeof(string));
                for (int i = 0; i < keysCount; i++)
                {
                    OpCode itemOpCode = (OpCode)typeof(OpCodes).GetField($"Ldc_I4_{i}").GetValue(null);
                    omcMthdIlGen.Emit(OpCodes.Dup);
                    omcMthdIlGen.Emit(itemOpCode);
                    omcMthdIlGen.Emit(OpCodes.Ldstr, keys[i]);
                    omcMthdIlGen.Emit(OpCodes.Stelem_Ref);
                }
                omcMthdIlGen.Emit(OpCodes.Callvirt, hasKeyMethod);
                omcMthdIlGen.Emit(OpCodes.Pop);
            }

            omcMthdIlGen.Emit(OpCodes.Ret);
            var dbContextOmcMthd = typeof(DbContext).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(p => p.Name == "OnModelCreating" && p.IsVirtual && p.GetParameters().Count() == 1);

            typeBuilder.DefineMethodOverride(omcMthdBldr, dbContextOmcMthd);
            return(typeBuilder.CreateType());
        }
Exemplo n.º 30
0
		internal static CodeEmitter Create(ConstructorBuilder cb)
		{
			return new CodeEmitter(cb.GetILGenerator());
		}
Exemplo n.º 31
0
    internal MyConstructorBuilder()
    {
// <Snippet1>
// <Snippet2>
// <Snippet3>
        MethodBuilder myMethodBuilder = null;

        AppDomain myCurrentDomain = AppDomain.CurrentDomain;
        // Create assembly in current CurrentDomain
        AssemblyName myAssemblyName = new AssemblyName();

        myAssemblyName.Name = "TempAssembly";
        // Create a dynamic assembly
        myAssemblyBuilder = myCurrentDomain.DefineDynamicAssembly
                                (myAssemblyName, AssemblyBuilderAccess.RunAndSave);
        // Create a dynamic module in the assembly.
        myModuleBuilder = myAssemblyBuilder.DefineDynamicModule("TempModule");
        FieldInfo myFieldInfo =
            myModuleBuilder.DefineUninitializedData("myField", 2, FieldAttributes.Public);
        // Create a type in the module
        TypeBuilder  myTypeBuilder   = myModuleBuilder.DefineType("TempClass", TypeAttributes.Public);
        FieldBuilder myGreetingField = myTypeBuilder.DefineField("Greeting",
                                                                 typeof(String), FieldAttributes.Public);

        Type[] myConstructorArgs = { typeof(String) };
        // Define a constructor of the dynamic class.
        ConstructorBuilder myConstructor = myTypeBuilder.DefineConstructor(
            MethodAttributes.Public, CallingConventions.Standard, myConstructorArgs);
        PermissionSet myPset = new PermissionSet(PermissionState.Unrestricted);

        // Add declarative security to the constructor.
        Console.WriteLine("Adding declarative security to the constructor.....");
        Console.WriteLine("The Security action to be taken is \"DENY\" and" +
                          " Permission set is \"UNRESTRICTED\".");
        myConstructor.AddDeclarativeSecurity(SecurityAction.Deny, myPset);
// </Snippet3>
        MethodAttributes myMethodAttributes = myConstructor.Attributes;
        Type             myAttributeType    = typeof(MethodAttributes);
        int myAttribValue = (int)myMethodAttributes;

        if (!myAttributeType.IsEnum)
        {
            Console.WriteLine("This is not an Enum");
        }
        FieldInfo[] myFieldInfo1 = myAttributeType.GetFields(BindingFlags.Public | BindingFlags.Static);
        Console.WriteLine("The Field info names of the Attributes for the constructor are:");
        for (int i = 0; i < myFieldInfo1.Length; i++)
        {
            int myFieldValue = (Int32)myFieldInfo1[i].GetValue(null);
            if ((myFieldValue & myAttribValue) == myFieldValue)
            {
                Console.WriteLine("   " + myFieldInfo1[i].Name);
            }
        }

        Type myType2 = myConstructor.DeclaringType;

        Console.WriteLine("The declaring type is : " + myType2.ToString());
// </Snippet2>
        ParameterBuilder myParameterBuilder1 =
            myConstructor.DefineParameter(1, ParameterAttributes.Out, "My Parameter Name1");

        Console.WriteLine("The name of the parameter is : " +
                          myParameterBuilder1.Name);
        if (myParameterBuilder1.IsIn)
        {
            Console.WriteLine(myParameterBuilder1.Name + " is Input parameter.");
        }
        else
        {
            Console.WriteLine(myParameterBuilder1.Name + " is not Input Parameter.");
        }
        ParameterBuilder myParameterBuilder2 =
            myConstructor.DefineParameter(1, ParameterAttributes.In, "My Parameter Name2");

        Console.WriteLine("The Parameter name is : " +
                          myParameterBuilder2.Name);
        if (myParameterBuilder2.IsIn)
        {
            Console.WriteLine(myParameterBuilder2.Name + " is Input parameter.");
        }
        else
        {
            Console.WriteLine(myParameterBuilder2.Name + " is not Input Parameter.");
        }
// </Snippet1>
        // Generate MSIL for the method, call its base class constructor and store the arguments
        // in the private field.
        ILGenerator myILGenerator3 = myConstructor.GetILGenerator();

        myILGenerator3.Emit(OpCodes.Ldarg_0);
        ConstructorInfo myConstructorInfo = typeof(Object).GetConstructor(new Type[0]);

        myILGenerator3.Emit(OpCodes.Call, myConstructorInfo);
        myILGenerator3.Emit(OpCodes.Ldarg_0);
        myILGenerator3.Emit(OpCodes.Ldarg_1);
        myILGenerator3.Emit(OpCodes.Stfld, myGreetingField);
        myILGenerator3.Emit(OpCodes.Ret);
        // Add a method to the type.
        myMethodBuilder = myTypeBuilder.DefineMethod
                              ("HelloWorld", MethodAttributes.Public, null, null);
        // Generate MSIL for the method.
        ILGenerator myILGenerator2 = myMethodBuilder.GetILGenerator();

        myILGenerator2.EmitWriteLine("Hello World from global");
        myILGenerator2.Emit(OpCodes.Ret);
        myModuleBuilder.CreateGlobalFunctions();
        myType1 = myTypeBuilder.CreateType();
    }