中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么實現在運行時生成C#的.NET類

發布時間:2021-11-24 13:41:34 來源:億速云 閱讀:138 作者:iii 欄目:開發技術

這篇文章主要介紹“怎么實現在運行時生成C#的.NET類”,在日常操作中,相信很多人在怎么實現在運行時生成C#的.NET類問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么實現在運行時生成C#的.NET類”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

為什么我需要在運行時生成類?

在運行時生產新類型的需求通常是由于運行時才知道類屬性,滿足性能要求以及需要在新類型中添加功能。當你嘗試這樣做的時候,你應該考慮的第一件事是:這是否真的是一個明智的解決方案。在深入思考之前,還有很多其他事情可以嘗試,問你自己這樣的問題:

  1. 我可以使用普通的類嗎

  2. 我可以使用Dictionary、Tuple或者對象數組(Array)?

  3. 我是否可以使用擴展對象

  4. 我確定我不能使用一個普通的類嗎?

如果你認為這仍然是必要的,請繼續閱讀下面的內容。

示例用例

作為一名開發人員,我將大量數據綁定到各種WPF Grids中。大多數時候屬性是固定的,我可以使用預定義的類。有時候,我不得不動態的構建網格,并且能夠在應用程序運行時更改數據。采取以下顯示ID和一些財務數據的類(FTSE和CAC是指數,其屬性代表指數價格):

public class PriceHolderViewModel : ViewModelBase{    public long Id { get; set; }    public decimal FTSE100 { get; set; }    public decimal CAC40 { get; set; }
}

如果我們僅對其中的屬性感興趣,該類定義的非常棒。但是,如果要使用更多屬性擴展此類,則需要在代碼中添加它,重新編譯并在新版本中進行部署。

相反的,我們可以做的是跟蹤對象所需的屬性,并在運行時構建類。這將允許我們在需要是不斷的添加和刪除屬性,并使用反射來更新它們的值。

// Keep track of my propertiesvar _properties = new Dictionary<string, Type>(new[]{   new KeyValuePair<string, Type>( "FTSE100", typeof(Decimal) ),   new KeyValuePair<string, Type>( "CAC40", typeof(Decimal) ) });

創建你的類型

下面的示例向您展示了如何在運行時構建新類型。你需要使用 **System.Reflection.Emit**庫來構造一個新的動態程序集,您的類將在其中創建,然后是模塊和類型。與舊的 ** .NET Framework**框架不同,在舊的版本中,你需要在當前程序的 AppDomain中創建程序集 ,而在 ** .NET Core**中, AppDomain不再可用。你將看到我使用GUID創建了一個新類型名稱,以便于跟蹤類型的版本。在以前,你不能創建具有相同名稱的兩個類型,但是現在似乎不是這樣了。

public Type GeneratedType { private set; get; }private void Initialise(){    var newTypeName = Guid.NewGuid().ToString();    var assemblyName = new AssemblyName(newTypeName);    var dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);    var dynamicModule = dynamicAssembly.DefineDynamicModule("Main");    var dynamicType = dynamicModule.DefineType(newTypeName,
            TypeAttributes.Public |
            TypeAttributes.Class |
            TypeAttributes.AutoClass |
            TypeAttributes.AnsiClass |
            TypeAttributes.BeforeFieldInit |
            TypeAttributes.AutoLayout,            typeof(T));     // This is the type of class to derive from. Use null if there isn't one
    dynamicType.DefineDefaultConstructor(MethodAttributes.Public |
                                        MethodAttributes.SpecialName |
                                        MethodAttributes.RTSpecialName);    foreach (var property in Properties)
        AddProperty(dynamicType, property.Key, property.Value);
    GeneratedType = dynamicType.CreateType();
}

在定義類型時,你可以提供一種類型,從中派生新的類型。如果你的基類具有要包含在新類型中的某些功能或屬性,這將非常有用。之前,我曾使用它在運行時擴展 ViewModel和 Serializable類型。

在你創建了 TypeBuilder后,你可以使用下面提供的代碼開始添加屬性。它創建了支持字段和所需的中間語言,以便通過 Getter和 Setter訪問它們。為每個屬性完成此操作后,可以使用 CreateType()創建類型的實例。

private static void AddProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType){    var fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);    var propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);    
    var getMethod = typeBuilder.DefineMethod("get_" + propertyName,
        MethodAttributes.Public |
        MethodAttributes.SpecialName |
        MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);    var getMethodIL = getMethod.GetILGenerator();
    getMethodIL.Emit(OpCodes.Ldarg_0);
    getMethodIL.Emit(OpCodes.Ldfld, fieldBuilder);
    getMethodIL.Emit(OpCodes.Ret);    var setMethod = typeBuilder.DefineMethod("set_" + propertyName,
          MethodAttributes.Public |
          MethodAttributes.SpecialName |
          MethodAttributes.HideBySig,          null, new[] { propertyType });    var setMethodIL = setMethod.GetILGenerator();
    Label modifyProperty = setMethodIL.DefineLabel();
    Label exitSet = setMethodIL.DefineLabel();
    setMethodIL.MarkLabel(modifyProperty);
    setMethodIL.Emit(OpCodes.Ldarg_0);
    setMethodIL.Emit(OpCodes.Ldarg_1);
    setMethodIL.Emit(OpCodes.Stfld, fieldBuilder);
    setMethodIL.Emit(OpCodes.Nop);
    setMethodIL.MarkLabel(exitSet);
    setMethodIL.Emit(OpCodes.Ret);
    propertyBuilder.SetGetMethod(getMethod);
    propertyBuilder.SetSetMethod(setMethod);
}

有了類型后,就很容易通過使用 Activator.CreateInstance()來創建它的實例。但是,你希望能夠更改已創建的屬性的值,為了做到這一點,你可以再次使用反射來獲取 propertyInfos并提取Set方法。一旦有了這些屬性,電影它們類設置屬性值就相對簡單了。

foreach (var property in Properties)
{    var propertyInfo = GeneratedType.GetProperty(property.Key);    var setMethod = propertyInfo.GetSetMethod();
    setMethod.Invoke(objectInstance, new[] { propertyValue });
}

現在,您可以在運行時使用自定義屬性來創建自己的類型,并具有更新其值的功能,一切就緒。 我發現的唯一障礙是創建一個可以存儲新類型實例的列表。 WPF中的DataGrid傾向于只讀取List的常規參數類型的屬性。 這意味著即使您使用新屬性擴展了基類,使用AutoGenerateProperties也只能看到基類中的屬性。 解決方案是使用生成的類型顯式創建一個新的List。 我在下面提供了如何執行此操作的示例:

var listGenericType = typeof(List<>);var list = listGenericType.MakeGenericType(GeneratedType);var constructor = list.GetConstructor(new Type[] { });var newList = (IList)constructor.Invoke(new object[] { });foreach (var value in values)
    newList.Add(value);

到此,關于“怎么實現在運行時生成C#的.NET類”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

广水市| 镇雄县| 中山市| 固原市| 运城市| 山西省| 名山县| 青田县| 木兰县| 绥阳县| 北票市| 崇左市| 历史| 治县。| 体育| 大丰市| 宜城市| 平凉市| 抚顺县| 浮梁县| 会昌县| 开江县| 新乡县| 梁山县| 郴州市| 株洲市| 白山市| 昌平区| 富宁县| 休宁县| 贡山| 凭祥市| 济南市| 罗源县| 前郭尔| 阿坝县| 广丰县| 金昌市| 太保市| 宝兴县| 马公市|