private static void CreateProperty(TypeBuilder tb, FieldBuilder fbInstance, PropertyInfo pi, MethodInfoHolder getMi, MethodInfoHolder setMi)
        {
            var name = pi.Name;
            var type = pi.PropertyType;

            var pb = tb.DefineProperty(name, PropertyAttributes.HasDefault, type, null);

            var getSetAttr    = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final;
            var mbGetAccessor = tb.DefineMethod("get_" + name, getSetAttr, type, Type.EmptyTypes);

            var getIL = mbGetAccessor.GetILGenerator();

            if (getMi == null)
            {
                getIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
                getIL.Emit(OpCodes.Throw);
            }
            else
            {
                getIL.Emit(OpCodes.Ldarg_0);
                getIL.Emit(OpCodes.Ldfld, fbInstance);
                getIL.Emit(OpCodes.Ldc_I4, getMi.ObjectIndex);
                getIL.Emit(OpCodes.Callvirt, ObjectContainer.GetGetMethodInfo());
                getIL.Emit(OpCodes.Isinst, getMi.ObjectType);
                getIL.Emit(OpCodes.Callvirt, getMi.MethodInfo);
                getIL.Emit(OpCodes.Ret);
            }

            var mbSetAccessor = tb.DefineMethod("set_" + name, getSetAttr, null, new Type[] { type });

            var setIL = mbSetAccessor.GetILGenerator();

            if (setMi == null)
            {
                setIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
                setIL.Emit(OpCodes.Throw);
            }
            else
            {
                setIL.Emit(OpCodes.Ldarg_0);
                setIL.Emit(OpCodes.Ldfld, fbInstance);
                setIL.Emit(OpCodes.Ldc_I4, setMi.ObjectIndex);
                setIL.Emit(OpCodes.Callvirt, ObjectContainer.GetGetMethodInfo());
                setIL.Emit(OpCodes.Isinst, setMi.ObjectType);
                setIL.Emit(OpCodes.Ldarg_1);
                setIL.Emit(OpCodes.Callvirt, setMi.MethodInfo);
                setIL.Emit(OpCodes.Ret);
            }

            pb.SetGetMethod(mbGetAccessor);
            pb.SetSetMethod(mbSetAccessor);
        }
        private static void CreateMethod(TypeBuilder tb, FieldBuilder fbInstance, MethodInfo mi, MethodInfoHolder instanceMi)
        {
            var paramTyleList = new List <Type>();

            foreach (var item in mi.GetParameters())
            {
                paramTyleList.Add(item.ParameterType);
            }

            var mb = tb.DefineMethod(mi.Name, MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, mi.ReturnType, paramTyleList.ToArray());

            var il = mb.GetILGenerator();

            if (instanceMi == null)
            {
                il.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
                il.Emit(OpCodes.Throw);
            }
            else
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, fbInstance);
                il.Emit(OpCodes.Ldc_I4, instanceMi.ObjectIndex);
                il.Emit(OpCodes.Callvirt, ObjectContainer.GetGetMethodInfo());
                il.Emit(OpCodes.Isinst, instanceMi.ObjectType);
                switch (paramTyleList.Count)
                {
                case 0:
                    break;

                case 1:
                    il.Emit(OpCodes.Ldarg_1);
                    break;

                case 2:
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldarg_2);
                    break;

                case 3:
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldarg_2);
                    il.Emit(OpCodes.Ldarg_3);
                    break;

                default:
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldarg_2);
                    il.Emit(OpCodes.Ldarg_3);

                    var sCount = Math.Min(paramTyleList.Count, 127);
                    for (int i = 4; i <= sCount; i++)
                    {
                        il.Emit(OpCodes.Ldarg_S, i);
                    }

                    for (int i = 128; i <= paramTyleList.Count; i++)
                    {
                        il.Emit(OpCodes.Ldarg, i);
                    }

                    break;
                }

                il.Emit(OpCodes.Callvirt, instanceMi.MethodInfo);
                il.Emit(OpCodes.Ret);
            }
        }
Ejemplo n.º 3
0
        public static Type DynamicTypeGen <TInterface>(Object[] instances, Type[] typeList)
            where TInterface : class
        {
            Type tInterface = typeof(TInterface);

            PropertyInfo[]    pisInterface     = tInterface.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            MethodInfo[]      misInterface     = tInterface.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            List <MethodInfo> misInterfaceList = new List <MethodInfo>();

            List <Type> tList = new List <Type>();

            foreach (var obj in instances)
            {
                tList.Add(obj.GetType());
            }

            Type[] tArray = tList.ToArray();

            foreach (var item in misInterface)
            {
                if (item.IsSpecialName == false)
                {
                    misInterfaceList.Add(item);
                }
            }

            List <MethodInfoHolder> miHolderList = new List <MethodInfoHolder>();

            for (int i = 0; i < tArray.Length; i++)
            {
                MethodInfo[] misImple = tArray[i].GetMethods(BindingFlags.Public | BindingFlags.Instance);
                foreach (var item in misImple)
                {
                    MethodInfoHolder h = new MethodInfoHolder(item, i, typeList[i]);
                    miHolderList.Add(h);
                }
            }

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

            ModuleBuilder mb =
                ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

            TypeBuilder tb = mb.DefineType(GetDynamicTypeName <TInterface>(instances),
                                           TypeAttributes.Public, null, new Type[] { tInterface });
            FieldBuilder fbInstances = tb.DefineField(
                "_container",
                typeof(TypeTemplate.ObjectContainer),
                FieldAttributes.Private);

            ConstructorBuilder ctor1 = tb.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName,
                CallingConventions.Standard,
                new Type[1] {
                typeof(TypeTemplate.ObjectContainer)
            });

            ILGenerator ctor1IL = ctor1.GetILGenerator();

            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Ldarg_1);
            ctor1IL.Emit(OpCodes.Stfld, fbInstances);
            ctor1IL.Emit(OpCodes.Ret);

            foreach (var item in pisInterface)
            {
                MethodInfoHolder getMi = FindGetMethodInfo(miHolderList, item);
                MethodInfoHolder setMi = FindSetMethodInfo(miHolderList, item);
                CreateProperty(tb, fbInstances, item, getMi, setMi);
            }

            foreach (var item in misInterfaceList)
            {
                MethodInfoHolder instanceMi = FindMethodInfo(miHolderList, item);
                CreateMethod(tb, fbInstances, item, instanceMi);
            }
            Type type = tb.CreateType();

            ab.Save(aName.Name + ".dll");
            return(type);
        }