zoukankan      html  css  js  c++  java
  • c# 动态生成继承类并实现序列化特性

    项目来源

    App传过来的字段是动态的,希望能保证扩展性,返回时,把所需要的字段与数据融合后再返回过去

    数据是第3方来源的,但是序列化后的结果又希望能并列返回

    如:App传过来 一个设备Id,客户Id等信息(该信息不定,特定的窗口传过来的字段值不同,如一个hash表)

    返回的结果是一个地址(省,市,县等字段)(再merge 设备id,客户id等字段)

    简单的结果集可以用 字典来返回,但是复杂的结果集就不适合了(代码必须相对优雅)

    解决方案: 将传过来的字段保存到字典里,然后 生成动态类继承数据类,并将字典数据一一对应到动态类的字段里.

    1.原始类

     public class Address
        {
            [JsonProperty(PropertyName = "province"), Description("省份")]
            public string Province { get; set; }
    
            [JsonProperty(PropertyName = "city"), Description("城市")]
            public string City { get; set; }
        }

    2.动态扩展该类(增加一个id属性,和一个 县市 属性)

     var assemblyName = new AssemblyName("DynamicProxy");
                var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
                    AssemblyBuilderAccess.RunAndSave);
                var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule", "DynamicProxy.dll");
                //定义公开,继承Object,无接口的类
                var typeBuilder = moduleBuilder.DefineType("AddressAddtional", TypeAttributes.Public | TypeAttributes.Serializable, typeof(Address), new Type[0]);
              
    
                var fieldId = typeBuilder.DefineField("id", typeof(int), FieldAttributes.Private);
                var fieldName = typeBuilder.DefineField("county", typeof(string), FieldAttributes.Private);
                var methodGetId = typeBuilder.DefineMethod("GetId", MethodAttributes.Public, typeof(int), null);
                var methodSetId = typeBuilder.DefineMethod("SetId", MethodAttributes.Public, null, new Type[] { typeof(int) });
                var ilGetId = methodGetId.GetILGenerator();
                ilGetId.Emit(OpCodes.Ldarg_0);//this 入栈
                ilGetId.Emit(OpCodes.Ldfld,fieldId);
                ilGetId.Emit(OpCodes.Ret);
                var ilSetId = methodSetId.GetILGenerator();
                ilSetId.Emit(OpCodes.Ldarg_0);//this 入栈
                ilSetId.Emit(OpCodes.Ldarg_1);//参数 入栈
                ilSetId.Emit(OpCodes.Stfld, fieldId);
                ilSetId.Emit(OpCodes.Ret);
    
                var methodGetCounty = typeBuilder.DefineMethod("GetCounty", MethodAttributes.Public, typeof(string), null);
                var methodSetCounty = typeBuilder.DefineMethod("SetCounty", MethodAttributes.Public, null, new Type[] { typeof(string) });
                var ilGetCounty = methodGetCounty.GetILGenerator();
                ilGetCounty.Emit(OpCodes.Ldarg_0);//this 入栈
                ilGetCounty.Emit(OpCodes.Ldfld, fieldName);
                ilGetCounty.Emit(OpCodes.Ret);
                var ilSetCounty = methodSetCounty.GetILGenerator();
                ilSetCounty.Emit(OpCodes.Ldarg_0);//this 入栈
                ilSetCounty.Emit(OpCodes.Ldarg_1);//参数 入栈
                ilSetCounty.Emit(OpCodes.Stfld, fieldName);
                ilSetCounty.Emit(OpCodes.Ret);
    
                var propertyId = typeBuilder.DefineProperty("Id", PropertyAttributes.None, typeof (int), null);
                CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeof(DescriptionAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "地址Id" });
                CustomAttributeBuilder customAttributeBuilder2 = new CustomAttributeBuilder(typeof(JsonPropertyAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "id" });
                propertyId.SetCustomAttribute(customAttributeBuilder);//字段描述 
                propertyId.SetCustomAttribute(customAttributeBuilder2);//JsonProperty 
                propertyId.SetGetMethod(methodGetId);
                propertyId.SetSetMethod(methodSetId);
    
                var propertyCounty = typeBuilder.DefineProperty("County", PropertyAttributes.None, typeof(string), null);
                customAttributeBuilder = new CustomAttributeBuilder(typeof(DescriptionAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "县区" });
                customAttributeBuilder2 = new CustomAttributeBuilder(typeof(JsonPropertyAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "county" });
                propertyCounty.SetCustomAttribute(customAttributeBuilder);//字段描述 
                propertyCounty.SetCustomAttribute(customAttributeBuilder2);//JsonProperty 
                propertyCounty.SetGetMethod(methodGetCounty);
                propertyCounty.SetSetMethod(methodSetCounty);
               
                
    
                var dynamicType = typeBuilder.CreateType();
                assemblyBuilder.Save("DynamicProxy.dll");
              
    
                instance = Activator.CreateInstance(dynamicType);
                instance.Id = 1001;
                instance.County = "天河区";
                instance.Province = "广东省";
                instance.City = "广州市";
               Console.WriteLine(JsonHelper.ToJson(instance) );
                #endregion

    3.动态生成的dll,代码如下(使用ILSpy查看)

    public class AddressAddtional : Address
    {
        private int id;
        private string county;
        [JsonProperty("id"), Description("地址Id")]
        public int Id
        {
            get
            {
                return this.id;
            }
            set
            {
                this.id = value;
            }
        }
        [JsonProperty("county"), Description("县区")]
        public string County
        {
            get
            {
                return this.county;
            }
            set
            {
                this.county = value;
            }
        }
        
    }

    4.执行结果为

  • 相关阅读:
    H.264 RTP PAYLOAD 格式
    ARM:移动GPU往PC GPU效能迈进
    汪墩一中复校设想
    jconsole 和jvisualVM 监控远程 spring boot程序
    jenkins 登录远程机器并执行脚本,脚本中有后台执行的程序无法执行解决方法。
    linux下的抓包工具tcpdump
    adb logcat查看某个进程的输出日志
    Flask-SQLAlchemy 中多表链接查询(不使用外键)
    使用cnpm 安装vue.js
    Jmeter在非GUI环境下传递参数(命令行&Jenkins配置)
  • 原文地址:https://www.cnblogs.com/zhshlimi/p/6943365.html
Copyright © 2011-2022 走看看