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.执行结果为