2011-04-23 38 views
1

我有一個基Question類及大量的類,從這個類派生像CheckboxQuestion類和RadioButtonQuestion如何使用反射來實例化基礎上的文字一類新的XML文件

程序遍歷XML代碼每一個這是一個問題裏面塊標記就會使一個新的元素基於標籤的名稱,是一個子類的問題類

 <question number="1"> 
      <RadioButtonQuestion> 
       <title>What is the right ...</title> 
       <choices> 
        <choice value="1">answer 1</choice> 
        <choice value="2">answer 2</choice> 
        <choice value="3">answer 3</choice> 
        <choice value="4">answer 4</choice> 
       </choices> 
      </RadioButtonQuestion> 
     </question> 

的迭代對所有T後他xml文件,我想把所有的問題在IEnumerable<Questions>問題是,我不知道如何使基礎上編寫的XML文檔中的文字一類新的

+1

這其實看起來更像是反序列化比反射... – 2011-04-23 01:11:25

+0

的情況@ Etienne de Martel沒有它沒有問題是基於文本我想做一個新的例子 – 2011-04-23 01:14:10

+0

這個問題很不清楚。我不確定你在問什麼。您是否試圖創建一個類的實例,因爲它的名稱是從XML文件中讀取的?您是否試圖根據XML模式創建一個從您的Question類派生的新類型?澄清這個問題,以及清理大小寫和標點符號,將幫助你得到更多的答案,並使它更容易找到有類似問題的人:) – 2011-04-23 21:50:44

回答

4

如果XML標籤直接反映了您的類的名稱,則可以使用Type.GetType()來確定相應的類型 - 請記住它需要完整的名稱空間(下面示例中的「測試」)。然後,您可以使用Activator.CreateInstance()來創建該類型的實例。

string xmlTagName = "RadioButtonQuestion"; 
Type type = Type.GetType("Test." + xmlTagName); 
var question = Activator.CreateInstance(type); 

還銘記記住這Activator.CreateInstance()返回object。如果根據標籤名稱確定了正確的類型,那麼總體可能會更好,然後以舊式的方式實例化一個實例。

+2

使用Activator.CreateInstance的一個有用的替代方法是使用反射獲得類型的構造函數,即: var question = type.GetConstructor(<構造函數的參數類型的數組> ).Invoke(<參數值的數組傳遞給構造函數>);' 對Activator.CreateInstance的一個優點是可以使用私有和內部構造函數以及公有函數,只需將BindingFlags.NonPublic傳遞爲'type.GetConstructor'的第二個參數。只是覺得我會提到,對於未來的讀者有類似的問題:) – 2011-04-23 21:56:35

+0

該死,我可以投票評論? – Kenn 2012-10-11 15:35:34

0
switch(input) 
{ 
     case optionA: 
      return Activator.CreateInstance(typeof(Bla)); 
     case optionB: 
      return Activator.CreateInstance(typeof(Blb)); 
} 

$ 0.02

任何額外可以添加Bla/Blo構造函數的參數

Activator.CreateInstance(typeof(Bla), 1, 2 ,3); 

實際上,它需要一個params對象數組。所以,如果你需要動態通過他們,

object[] dynparams = new object[] { 1,2, "more", 4.5, new List<int>() }; 
... 
return Activator.CreateInstance(typeof(Bla), dynparams); 

許多其他重載存在,read about them here

現在,我不知道你的任何typenames的,但你將能夠做到

Object obj = Activator.CreateInstance(null, "Namespace1.MyClass1", dynparams); 
+0

我不想做這個switch語句,我甚至不想指定類型。我想要的是你讀的這個字符串認爲它是類名,並且創建了這個類的一個新實例(字符串),並將一個值傳遞給類構造函數 – 2011-04-23 01:03:16

+1

爲什麼你會使用'Activator.CreateInstance(typeof(Bla))'而不是'新的Bla()'? – Gabe 2011-04-23 01:04:38

+0

@Nadeem:[讀取重載](http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx)。它包含你想要的。我只是不知道你的類名:) @Gabe:因爲當然typeof(Bla())可以是任何東西。 – sehe 2011-04-23 10:06:29

2

假設類型都在當前執行的程序集,這應該由實例名稱的類,而無需switch語句:

public object InstantiateClass(string name, params object[] args) 
{ 
    return Activator.CreateInstance(this.GetType().Assembly.FullName, name, args); 
} 
+0

如何傳遞'this.GetType()。Assembly.FullName'與傳遞'null'不同? – Gabe 2011-04-23 01:07:40

+0

這不是,我只是更願意明確地表達意思。如果他的類型不在當前正在執行的程序集中,則可以用正確的程序集名稱替換它。 – BrandonZeider 2011-04-23 01:09:26

+0

簡潔明瞭! – sehe 2011-04-23 10:10:26

相關問題