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.執行結果為

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM