2016-07-05 51 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