2011-01-28 100 views
7

好吧,我現在整天都在想這個想法,而且我已經達到了我承認我只是不知道的部分。可能我所做的只是愚蠢的,還有更好的辦法,但這是我思想給我帶來的地方。如何將類型名稱轉換爲字符串?

我試圖用一個通用的方法來加載形式的WinForms:

protected void LoadForm<T>(ref T formToShow, bool autoLoaded) where T : FormWithWorker, new() 
{ 
    // Do some stuff 
} 

的形式由一個ToolStripMenuItem(通過項目的選擇或使用打開Windows菜單項)加載。它們是延遲加載的,因此MDI父級中有表單的字段,但在需要它們之前它們爲空。我有一個用於處理所有菜單項點擊的ToolStripMenuItem_Click的常用方法。除了ToolStripMenuItem的名稱匹配爲它們對應的表單類名稱選擇的模式之外,該方法沒有真正知道調用哪個表單的方法。因此,使用ToolStripMenuItem的名稱,我可以確定被請求的表單類型的名稱以及分配用於存儲該表單引用的專用字段的名稱。

使用這個,我可以使用硬編碼類型和字符串匹配的增長/收縮switch語句來調用具有特定類型集的方法(不受歡迎),或者我可以使用Reflection獲取字段並創建實例的類型。對我來說問題是,System.Activator.CreateInstance提供了一個ObjectHandler,它不能轉換爲我需要的類型。這裏是我到目前爲止的代碼段:

string formName = "_form" + ((ToolStripMenuItem)sender).Name.Replace("ToolStripMenuItem", ""); 
string formType = formName.Substring(1); 

FieldInfo fi = this.GetType().GetField(formName, BindingFlags.NonPublic | BindingFlags.Instance); 

FormWithWorker formToLoad = (FormWithWorker)fi.GetValue(this); 
if (formToLoad == null) 
{ 
    formToLoad = (????)System.Activator.CreateInstance("MyAssemblyName", formType); 
} 

this.LoadForm(ref formToLoad, false); 
fi.SetValue(this, formToLoad); 

我知道,去爲(????)類型的字符串名稱,但在編譯的時候,我不知道是什麼類型,因爲它改變。我嘗試了很多方法來讓這個演員/實例化工作,但都沒有成功。我非常想知道是否有可能只知道這種類型的字符串。我嘗試使用Type.GetType(string, string)來執行轉換,但編譯器不喜歡它。如果有人對如何動態加載表單有不同的想法,因爲我只是在愚蠢地做,請讓我知道。

+0

make formToLoad對象,並將其轉換爲LoadForm和SetValue點處的FormWithWorker? – asawyer 2011-01-28 19:14:25

回答

5

你會與需要Type和使用例如other overload更好Type.GetType(string)

FormWithWorker formToLoad = (FormWithWorker)fi.GetValue(this); 
if (formToLoad == null) 
{ 
    formToLoad = 
     (FormWithWorker)System.Activator.CreateInstance(Type.GetType("MyNamespace.MyFormType")); 
} 
12

此問題通常通過將所有可能類型轉換爲通用基類或接口來解決。

在C#4中,您也可以將其分配給dynamic變量以保存返回值並調用任意方法。方法將遲到。不過,我寧願儘可能堅持以前的解決方案。

+0

投票表決。我使用一個界面做了非常類似的事情,它很好地工作。 – Chuck 2011-01-28 19:19:47

+0

我嘗試了這種方法,但我遇到的問題是它最終分配的動態類型是基類而不是實際的類,所以當調用SetValue方法時,它拋出了一個類型轉換異常。 – 2011-02-01 11:41:38

+0

@Joel作爲其他答案指出,你應該使用返回對象本身的重載。顯然,您使用的重載對於激活.NET遠程對象很有用。 – 2011-02-01 12:01:47

2

根據你所擁有的,FormWithWorker必須(至少)作爲基類你實例化的類型,那麼你可以這樣做:

FormWithWorker formToLoad = (FormWithWorker)fi.GetValue(this); 
if (formToLoad == null) 
{ 
    formToLoad = (FormWithWorker)System.Activator.CreateInstance("MyAssemblyName", formType); 
} 
0

雖然通用接口是解決這個的一種方式問題,接口對所有場景都不實用。上面的決定是與工廠模式(switch語句 - 具體類選擇)一起使用還是使用反射。有一個堆棧文章解決了這個問題。我相信你可以直接在此適用於您的問題:

Method Factory - case vs. reflection

相關問題