項目來源
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.執行結果為

