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[]);
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 = ;
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.执行结果为

c# 动态生成继承类并实现序列化特性的更多相关文章
- 根据数据库记录动态生成C#类及其公共属性并动态执行的解决方案
原文:根据数据库记录动态生成C#类及其公共属性并动态执行的解决方案 问题: C#中,想动态产生这么一个类: public class StatisticsData { public ...
- 分析JVM动态生成的类
总结思考:让jvm创建动态类及其实例对象,需要给它提供哪些信息? 三个方面: 1.生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知: 2.产生的类字节码必须有个一个关联的类加载器对象: 3.生 ...
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架
类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...
- JAVA基础加强(张孝祥)_类加载器、分析代理类的作用与原理及AOP概念、分析JVM动态生成的类、实现类似Spring的可配置的AOP框架
1.类加载器 ·简要介绍什么是类加载器,和类加载器的作用 ·Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader ...
- Emit动态生成代理类用于监控对象的字段修改
利用Emit动态生成代理对象监控对象哪些字段被修改,被修改为什么值 被Register的对象要监控的值必须是Virtual虚类型 必须使用CreateInstance创建对象 必须使用DynamicP ...
- Java——动态生成POJO类
package com.java.test.dynamicpojo; import java.io.ByteArrayOutputStream; import java.io.IOException; ...
- 动态生成Person类的对象 代码参考
#include <iostream> #include <string> using namespace std; class Person { private: strin ...
- Java中动态代理技术生成的类与原始类的区别 (转)
用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...
- Java中动态代理技术生成的类与原始类的区别
用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...
随机推荐
- MySQL - pt-query-digest的下载与使用
对于脚本文件,是可以执行的,我们不用安装.所以,但是这个脚本文件没有执行的权限,所以,我们首先赋予这个脚本文件的可执行的权限. 再次查看文件的信息后. 已经有了执行的权限了. 运行脚本的时候,可要注意 ...
- rest 参数和扩展运算符
rest 参数和扩展运算符 rest 参数的形式为 ...变量名:扩展运算符是三个点 .... rest 参数 function add(...values) { console.log(values ...
- Linux 下安装tomcat 服务器
1. 下载tomcat wget http://apache.fayea.com/tomcat/tomcat-7/v7.0.68/bin/apache-tomcat-7.0.68.tar.gz tar ...
- Java反射学习:深入学习Java反射机制
一.Java反射的理解(反射是研究框架的基础之一) Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的 ...
- Git代码冲突常见解决方法
在发布这个配置文件的时候,会发生代码冲突: error: Your local changes to the following files would be overwritten by merge ...
- Windows中与系统关联自己开发的程序(默认打开方式、图标、右击菜单等)
1. 默认打开方式 1.1. 代码支持 在Windows下,某个特定后缀名类型的文件,如果要双击时默认用某个程序(比如自己开发的WinForm程序)打开,代码中首先肯定要支持直接根据这个文件进行下一步 ...
- SSI简介 与 nginx开启SSI
Server Side Include : 服务器端嵌入 原理 : 将内容发送到浏览器之前,可以使用“服务器端包含 (SSI)”指令将文本.图形或应用程序信息包含到网页中.因为包含 SSI 指令的文件 ...
- 3人从小公寓创业,到世界最大引擎公司,Unity创始人谈14年...
Unity创始人David Helgason出席了5月11 - 13日在上海举办的Unite 2017 Shanghai,并在大会期间接受了游戏陀螺的专访,动情地讲述了这14年来从3人在公寓创业,到成 ...
- sysbase 笔记
Alter 在已有数据的表中新增一个字段: ALTER table ciecdb.ciec.eci_mansmfile ADD num int default 0;
- ajax-3验证
$("#formBtn").click(function () { // var regName =/^[\u4e00-\u9fa5]{2,10}$/;//姓名只能是汉字切2-10 ...