emit 实现动态类,动态实现接口

一,emit  实现动态类,动态实现接口,或者继承某个类, 或者作为接口的远程调用rpc 的参考

 public class DynamicProxyGenerator
    {



        private const string DynamicAssemblyName = "DynamicAssembly";//动态程序集名称
        private const string DynamicModuleName = "DynamicAssemblyModule";
        private const string DynamicModuleDllName = "DynamicAssembly.dll";//动态模块名称
        private const string ProxyClassNameFormater = "{0}Proxy";
        private const string ModifiedPropertyNamesFieldName = "ModifiedPropertyNames";
        private const MethodAttributes GetSetMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.HideBySig;

        /// <summary>
        /// 创建动态程序集,返回AssemblyBuilder
        /// </summary>
        /// <param name="isSavaDll"></param>
        /// <returns></returns>
        private static AssemblyBuilder DefineDynamicAssembly(bool isSavaDll = false)
        {
            //动态创建程序集
            AssemblyName DemoName = new AssemblyName(DynamicAssemblyName);
            AssemblyBuilderAccess assemblyBuilderAccess = isSavaDll ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run;
            AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, assemblyBuilderAccess);
            return dynamicAssembly;
        }

        /// <summary>
        /// 创建动态模块,返回ModuleBuilder
        /// </summary>
        /// <param name="isSavaDll"></param>
        /// <returns>ModuleBuilder</returns>
        private static ModuleBuilder DefineDynamicModule(AssemblyBuilder dynamicAssembly, bool isSavaDll = false)
        {
            ModuleBuilder moduleBuilder = null;
            //动态创建模块
            if (isSavaDll)
                moduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName, DynamicModuleDllName);
            else
                moduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName);
            return moduleBuilder;
        }

        /// <summary>
        /// 创建动态代理类,重写属性Get Set 方法,并监控属性的Set方法,把变更的属性名加入到list集合中,需要监控的属性必须是virtual
        /// 如果你想保存修改的属性名和属性值,修改Set方法的IL实现
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="isSavaDynamicModule"></param>
        /// <returns></returns>
        public static T CreateDynamicProxy<T>(bool isSavaDynamicModule = false)
        {
            // Type modifiedPropertyNamesType = typeof(HashSet<string>);

            Type typeNeedProxy = typeof(T);
            AssemblyBuilder assemblyBuilder = DefineDynamicAssembly(isSavaDynamicModule);
            //动态创建模块
            ModuleBuilder moduleBuilder = DefineDynamicModule(assemblyBuilder, isSavaDynamicModule);
            string proxyClassName = string.Format(ProxyClassNameFormater, typeNeedProxy.Name);
            //动态创建类代理
            TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(proxyClassName, TypeAttributes.Public, typeNeedProxy);
            //定义一个变量存放属性变更名
            //  FieldBuilder fbModifiedPropertyNames = typeBuilderProxy.DefineField(ModifiedPropertyNamesFieldName, modifiedPropertyNamesType, FieldAttributes.Public);

            /*
             * 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码
               ModifiedPropertyNames = new List<string>();
            */
            //ConstructorBuilder constructorBuilder = typeBuilderProxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
            //ILGenerator ilgCtor = constructorBuilder.GetILGenerator();
            //ilgCtor.Emit(OpCodes.Ldarg_0);//加载当前类
            //ilgCtor.Emit(OpCodes.Newobj, modifiedPropertyNamesType.GetConstructor(new Type[0]));//实例化对象入栈
            //ilgCtor.Emit(OpCodes.Stfld, fbModifiedPropertyNames);//设置fbModifiedPropertyNames值,为刚入栈的实例化对象
            //ilgCtor.Emit(OpCodes.Ret);//返回

            //获取被代理对象的所有属性,循环属性进行重写
            PropertyInfo[] properties = typeNeedProxy.GetProperties();

            //PropertyInfo[] addpro = typeof(BaseAddPropertie).GetProperties();
            //var listpro = properties.ToList();
            //listpro.AddRange(addpro);
            //properties = listpro.ToArray();
            foreach (PropertyInfo propertyInfo in properties)
            {
                string propertyName = propertyInfo.Name;
                Type typePepropertyInfo = propertyInfo.PropertyType;
                //动态创建字段和属性
                FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_" + propertyName, typePepropertyInfo, FieldAttributes.Private);
                PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.None, typePepropertyInfo, null);

                //重写属性的Get Set方法
                var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.HideBySig, typePepropertyInfo, Type.EmptyTypes);
                var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.HideBySig, null, new Type[] { typePepropertyInfo });

                //il of get method
                var ilGetMethod = methodGet.GetILGenerator();
                ilGetMethod.Emit(OpCodes.Ldarg_0);
                ilGetMethod.Emit(OpCodes.Ldfld, fieldBuilder);
                ilGetMethod.Emit(OpCodes.Ret);
                //il of set method
                ILGenerator ilSetMethod = methodSet.GetILGenerator();
                ilSetMethod.Emit(OpCodes.Ldarg_0);
                ilSetMethod.Emit(OpCodes.Ldarg_1);
                ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder);
                //ilSetMethod.Emit(OpCodes.Ldarg_0);
                //ilSetMethod.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);
                //  ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name);
                // ilSetMethod.Emit(OpCodes.Callvirt, modifiedPropertyNamesType.GetMethod("Add", new Type[] { typeof(string) }));
                //ilSetMethod.Emit(OpCodes.Pop);
                ilSetMethod.Emit(OpCodes.Ret);

                //设置属性的Get Set方法
                propertyBuilder.SetGetMethod(methodGet);
                propertyBuilder.SetSetMethod(methodSet);
            }

            //使用动态类创建类型
            Type proxyClassType = typeBuilderProxy.CreateType();
            //保存动态创建的程序集
            if (isSavaDynamicModule)
                assemblyBuilder.Save(DynamicModuleDllName);
            //创建类实例
            var instance = Activator.CreateInstance(proxyClassType);
            return (T)instance;
        }






        /// <summary>
        /// 创建动态代理类,重写属性Get Set 方法,并监控属性的Set方法,把变更的属性名加入到list集合中,需要监控的属性必须是virtual
        /// 如果你想保存修改的属性名和属性值,修改Set方法的IL实现
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="isSavaDynamicModule"></param>
        /// <returns></returns>
        public static  Type CreateDynamicProxyNewTest<T,I>(bool isSavaDynamicModule = false)
        {
            // Type modifiedPropertyNamesType = typeof(HashSet<string>);

            Type typeNeedProxy = typeof(T);
            AssemblyBuilder assemblyBuilder = DefineDynamicAssembly(isSavaDynamicModule);
            //动态创建模块
            ModuleBuilder moduleBuilder = DefineDynamicModule(assemblyBuilder, isSavaDynamicModule);
            string proxyClassName = string.Format(ProxyClassNameFormater, typeNeedProxy.Name);
            //动态创建类代理
            TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(proxyClassName, TypeAttributes.Public, typeof(T),  new Type[] { typeof(I) });
            //定义一个变量存放属性变更名
            //  FieldBuilder fbModifiedPropertyNames = typeBuilderProxy.DefineField(ModifiedPropertyNamesFieldName, modifiedPropertyNamesType, FieldAttributes.Public);

            /*
             * 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码
               ModifiedPropertyNames = new List<string>();
            */
            //ConstructorBuilder constructorBuilder = typeBuilderProxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
            //ILGenerator ilgCtor = constructorBuilder.GetILGenerator();
            //ilgCtor.Emit(OpCodes.Ldarg_0);//加载当前类
            //ilgCtor.Emit(OpCodes.Newobj, modifiedPropertyNamesType.GetConstructor(new Type[0]));//实例化对象入栈
            //ilgCtor.Emit(OpCodes.Stfld, fbModifiedPropertyNames);//设置fbModifiedPropertyNames值,为刚入栈的实例化对象
            //ilgCtor.Emit(OpCodes.Ret);//返回




            //获取被代理对象的所有属性,循环属性进行重写
            //PropertyInfo[] properties = typeNeedProxy.GetProperties();
            PropertyInfo[] properties = typeof(I).GetProperties();

            foreach (PropertyInfo propertyInfo in properties)
            {
                string propertyName = propertyInfo.Name;
                Type typePepropertyInfo = propertyInfo.PropertyType;
                //动态创建字段和属性
                FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_" + propertyName, typePepropertyInfo, FieldAttributes.Private);
                PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.SpecialName, typePepropertyInfo, null);



                //var ttsoveride = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Virtual | MethodAttributes.HideBySig;
             var ttp=    MethodAttributes.Public | MethodAttributes.HideBySig |
               MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final;

                //重写属性的Get Set方法
                var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, ttp, typePepropertyInfo, Type.EmptyTypes);
                var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, ttp, null, new Type[] { typePepropertyInfo });

                //il of get method
                var ilGetMethod = methodGet.GetILGenerator();
                ilGetMethod.Emit(OpCodes.Ldarg_0);
                ilGetMethod.Emit(OpCodes.Ldfld, fieldBuilder);
                ilGetMethod.Emit(OpCodes.Ret);
                //il of set method
                ILGenerator ilSetMethod = methodSet.GetILGenerator();
                ilSetMethod.Emit(OpCodes.Ldarg_0);
                ilSetMethod.Emit(OpCodes.Ldarg_1);
                ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder);
                //ilSetMethod.Emit(OpCodes.Ldarg_0);
                //ilSetMethod.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);
                //  ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name);
                // ilSetMethod.Emit(OpCodes.Callvirt, modifiedPropertyNamesType.GetMethod("Add", new Type[] { typeof(string) }));
                //ilSetMethod.Emit(OpCodes.Pop);
                ilSetMethod.Emit(OpCodes.Ret);

                //设置属性的Get Set方法
                propertyBuilder.SetGetMethod(methodGet);
                propertyBuilder.SetSetMethod(methodSet);
            }


          

            //使用动态类创建类型
            Type proxyClassType = typeBuilderProxy.CreateType();
            //保存动态创建的程序集
            if (isSavaDynamicModule)
                assemblyBuilder.Save(DynamicModuleDllName);
            //创建类实例
            //var instance = Activator.CreateInstance(proxyClassType);
            return proxyClassType;
        }












        /// <summary>
        /// 获取属性的变更名称,
        /// 此处只检测调用了Set方法的属性,不会检测值是否真的有变
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static HashSet<string> GetModifiedProperties(object obj)
        {
            FieldInfo fieldInfo = obj.GetType().GetField(ModifiedPropertyNamesFieldName);
            if (fieldInfo == null) return null;
            object value = fieldInfo.GetValue(obj);
            return value as HashSet<string>;
        }
    }

参考资料: https://www.cnblogs.com/viclgd/archive/2011/03/28/1998122.html

https://blog.csdn.net/lishuangquan1987/article/details/84312514  

  

原文地址:https://www.cnblogs.com/bkyrslf/p/12677454.html