2016-07-05 30 views
0

我有一個主實例存儲裏面帶有選項的各種子類實例。如何用反射修復空的子類實例

Class MainClass 
{ 
    public bool b; 
    public int i; 
    public List l = new List(); 

    Class SubClass1 
    { 
     ... 
    } 
    public SubClass1 sub1 = new SubClass1(); 

    Class SubClass2 
    { 
     ... 
    } 
    public SubClass2 sub2 = new SubClass2(); 
} 

現在,當啓動所有類都正確instatiated,然後設置一些選項,並結果序列化。

問題出現時(出於各種原因)我必須更改實例的名稱。 例如SubClass2 ----> SubClassB 因此,反序列化SubClassB顯然是空的。

所以我必須解決這個缺點,並且我已經關於反射。像[僞] 東西

foreach(var subclass in MainClass) 
{ 
    if(subclass is null) 
    { 
     Type subClassType = typeof(subclass); 
     subclass = new subClassType(); 
    } 
} 

預先感謝您的任何幫助。

---添加完整性從thehennny的提示解決方案---

private void CheckAndFixNullInstances() 
{ 

    easyRunData.OptionsReport = null; 

    Type fieldsType = typeof(EasyRunBinSerializableData); 
    FieldInfo[] fields = fieldsType.GetFields(BindingFlags.Public | BindingFlags.Instance); 

    for (int i = 0; i < fields.Length; i++) 
    { 
     string str = fields[i].Name + " " + fields[i].GetValue(easyRunData); 
     if (fields[i].GetValue(easyRunData) == null) 
     { 
      string strFieldType = fields[i].FieldType.AssemblyQualifiedName; 
      Type t = Type.GetType(strFieldType); 
      object item; 
      item = Activator.CreateInstance(t); 
      fields[i].SetValue(easyRunData, item); 
     } 
    } 
} 
+0

請嘗試更好地解釋什麼情況..你是否更改類型或實例的名稱?當你是否改變它?在MainClass的foreach中獲得什麼?無論如何,'新的subClassType()'是沒有意義的..也許你想'Activator.CreateInstance(typeof(subClass))' –

+0

對不起,沒有足夠清楚。這種情況是,我用MainClass爲客戶提供了帶有子類實例的子程序:subclass1,subclass2。然後我序列化Mainclass值。之後(由於各種原因)我改變了子類subclass2 ---> subclassB的名字。現在反序列化子類B時顯然是空的,我必須採取行動。 – Patrick

+0

啊......你打破向後兼容的一個經典問題,你意識到你可以改變類的名稱爲你想要的任何東西,只要你將它連續化爲與以前一樣的名字即可。例如如果您要序列化爲XML,則可以使用XML屬性來說明您的類轉換的元素名稱! https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute(v=vs.110).aspx – Ruskin

回答

1

我不熟悉xml反序列化過程,但基本上需要的是循環遍歷特定對象的所有字段,並用字段類型的新對象填充所有空字段。

要獲取該類型的所有字段,您必須使用suitable Type.GetFields overload。 然後,您可以遍歷FieldInfo對象,並調用FieldInfo.GetValue Method。 做完空檢查之後,您可以通過傳入FieldInfo.FieldType Property作爲參數,並使用FieldInfo.SetValue Method將其存儲在字段中,從而創建一個新對象並使用Activator.CreateInstance Method

+0

好吧,我差不多在那裏!我只需要知道如何設置新的實例。請看我爲你編輯。 – Patrick

+0

您可以使用我的答案中鏈接的Activator.CreateInstance方法創建一個新對象。 – thehennyy

-1

的,你不能從一個空對象的任何類型的信息上面將無法工作。基本上,當你序列化對象時,你會想要存儲你期望的類的完全限定名。然後,當你反序列化它時,你可以閱讀這個值。如果對象爲「null」,則可以創建完全限定類型的實例。

注意:在引號中注意「null」,因爲這裏使用「null」語義表示某些不存在且不一定是空對象的東西。

NBB:我已經在Github項目中解決了這個問題,我歡迎您使用它(https://github.com/ruskindantra/extensions/blob/master/RuskinDantra.Extensions/DataStructures/XmlSerializableInterfaceList.cs)。

+0

很好,這很清楚。這就是說,我無法從null實例獲取信息是公平的,但是我應該能夠獨立於它的實例爲null或不正確的事實迭代所有主類的子類? – Patrick

+0

在你的例子中,哪裏是存儲所有子類的集合?基本上是的,如果你把它們全部存儲在一個集合中,你可以迭代它,但是你怎麼知道一個空的Subclass1需要關聯到一個新的SubclassA?信息存儲在哪裏? – Ruskin

+0

好吧,也許這是問題所在。沒有收集只有子類的實例。這就是爲什麼我想到迭代throgh思考。 – Patrick