2017-05-19 58 views
0

我的地方,我們在表中添加下列值動態地在現有的類C#運行時添加的屬性

  • 產品名稱
  • 產品編號
  • 產品代碼
一個UI

我有一個現有的類產品與一些現有的屬性

我找這將在現有的類產品在運行時(動態),當用戶在表中增加值

+0

您不能在運行時修改類定義,除非您遇到一些非常複雜的東西並編寫一些部分類,在運行時編譯成dll並將它們加載到內存中。聽起來就像你只需要一個Dictionary ,所以你可以存儲值並給它們一個名字。 – CathalMF

+1

實際上忽略了我之前關於在運行時編譯部分類的聲明,這甚至不可能。 – CathalMF

+0

好的,謝謝CathalMF – amethianil

回答

2

定義添加屬性的方法:

public class Product 
{ 
    public string ProductID { get; set; } 
    //product in a product search listing 
    public string StoreName { get; set; } 
    public string SearchToken { get; set; } 
    public Dictionary<string, object> Fields { get; set; } 
} 

用法:

var Prod = new Product(); 
Prod.Fields.Add("MyCustomFieldString", "my value here"); 
Prod.Fields.Add("MCustomFieldInt", 123); 

MessageBox.Show(Prod.Fields[MyCustomFieldString].ToString()); 
MessageBox.Show(Prod.Fields[MCustomFieldInt].ToString()); 
+0

好的感謝CathalMF,但我期待這個新添加的屬性將作爲永久屬性存在於產品類 – amethianil

+1

@amethianil Permanant屬性將要求您更改代碼,這意味着在運行時編譯和替換dll。這對於簡單添加新的搜索欄來說似乎很瘋狂。 – CathalMF

2

我不知道在運行時定義屬性的方法,但是另一種實現您需要的方法是在C#中使用名爲ExpandoObject的動態對象。

你首先需要聲明你的動態對象,它在內部使用一種字典,然後你可以添加你的屬性。

using System.Dynamic; 
dynamic newobj = new ExpandoObject(); 

//I can add properties during compile time such as this 
newobj.Test = "Yes"; 
newobj.JValue = 123; 

//Or during runtime such as this (populated from two text boxes) 
AddProperty(newobj, tbName.Text, tbValue.Text); 

public void AddProperty(ExpandoObject expando, string name, object value) 
{ 
    var exDict = expando as IDictionary<string, object>; 
    if (exDict.ContainsKey(propertyName)) 
     exDict[propertyName] = propertyValue; 
    else 
    exDict.Add(propertyName, propertyValue); 
} 

我在這裏一個解決方案中使用了一次:Flattern child/parent data with unknown number of columns

但這些來源也許可以更好地解釋它; https://www.oreilly.com/learning/building-c-objects-dynamically

https://weblog.west-wind.com/posts/2012/feb/08/creating-a-dynamic-extensible-c-expando-object

https://docs.microsoft.com/en-us/dotnet/articles/csharp/programming-guide/types/using-type-dynamic

但是,我不知道這會真的爲您提供了使用簡單的Dictionary<string, object>

+0

好的jason.kaisersmith謝謝你的回覆。我看起來不像ExpandoObject,因爲我們只能在運行時使用這個ExpandoObject對象。但我希望新添加的屬性將作爲屬性在我的課程中永久存在。將來我們將使用它作爲類屬性。如果一個用戶在表中添加了一個新字段,那麼它會自動添加爲我的Product類中的屬性 – amethianil

0

任何真正的優勢,你需要澄清(也許你自己)你需要什麼,或者我會說,你想要什麼。

編譯完代碼後,將根據您的類型\方法\字段生成元數據。有很多表格(45個更具體)來描述你的數據。

所以,如果你想添加新的屬性到某種類型,你需要添加新的行到元數據表。要添加新行,您需要編譯代碼,您需要

那麼什麼是Refelection.Emit?是在您的應用中動態創建新數據的一種方式。有了這個,你創建一個動態組件,動態類型,動態方法,添加一些IL,然後你去。但是,所有這一切都是在內存。而不是你想要的。

所以,或者動態數據使用Emit \ ExpandoObject,或靜態數據通過向代碼添加屬性並編譯它。

你也有一種運行時編譯方式之間的方法,它通過使用它來調用Mono.Cecil,你可以通過代碼添加新的屬性來鍵入,然後編譯它並加載新的DLL到你的AppDomain或者只是關閉應用程序並重新享用午餐。它可以自動,只需通過代碼。沒有什麼魔力,它會將數據添加到程序集中的元數據表中,但它可以縮短手動執行此操作的方式。

但還有一個選項,我相信你知道它。我正在使用Visual Studio,你可能聽說過Edit and Continue(EnC)。此功能實際上是將新代碼寫入您的正在運行的程序集,並將新數據(僅限新增)添加到元數據中。

所以,我不能告訴你,你應該做的,因爲我不知道到底是什麼你的情況下,有是,人們希望當他們不再需要他們極端的解決方案的情況下,但如果你真的必須選擇要將新的數據添加到已運行的程序集中,EnC可以成爲解決方案。要使用EnC,請查看Roslyn代碼中的功能(您可能想要檢查其測試以瞭解如何使用)。之後,看看@Josh Varty例子here

所有我寫的,我真的(X3)不認爲你需要做出一些瘋狂的你所需要的。我相信有一個更好,簡單的方法來做到這一點。

+0

好的,謝謝Dudi Keleti - 我已經使用ExpandoObjexct – amethianil

相關問題