2010-06-29 80 views
10

我想知道是否有可能做點什麼。我有一個函數讀取一個xml文件,並根據文件內容向表單添加控件。像這樣的XML節點將創建它:我可以在C#中使用「類」類型嗎?

<Button Top="300" Left="100">Automatic</Button> 

我有保存控制回xml文件,如果我在編輯模式下添加任何功能。它正在工作,但我想知道是否有更簡單的方法。目前,我的代碼看起來像這樣創建的每個控件的一個實例:

  switch (xmlchild.Name) 
      { 
       // Create a new control whose type is specified. 
       case "Button": 
        c = new Button(); 
        break; 
       case "Label": 
        c = new Label(); 
        break; 
       default: 
        c = null; 
        break; 
      } 

但是,當我想用​​更多類型的控件,我將需要繼續增加開關的情況。我可以做一些只會帶上文字並添加該類型的控件嗎?我會很感激任何反饋!

謝謝!

+0

你可以調用你的類「MyXml *」,其中*是Button,Label等,並使用反射。 – simendsjo 2010-06-29 15:03:14

+0

如果你使用WPF你可以使用XamlReader/Writer類 – 2010-06-29 15:03:44

回答

2

如果你控制XML文件的內容,那麼是的。你可以使用:

string fullNameSpace = "System.Windows.Controls."; 
Type controlType = Type.GetType(fullNameSpace + xmlchild.Name); 
if(controlType != null) 
{ 
    // get default constructor... 
    ConstructorInfo ctor = controlType.GetConstructor(Type.EmptyTypes); 
    object control = ctor.Invoke(null); 
} 

你可以同時使用Activator類清潔本了一下:

object control = Activator.CreateInstance("System.Windows.Presentation", 
              xmlchild.Name); 

或者,如果你可以創建一個有效的XAML文件,你可以使用XamlReader恢復控制樹。

+0

+1:謝謝你教我關於Type.EmptyTypes(也是一個很好的答案,但只能投票一次) – 2010-06-29 15:06:42

+0

+1儘管上面的代碼可以工作,問題在於類型名稱必須是正確的,因此開發人員不會無法避免檢查控件的名稱。最後會有一個類似switch或if/else塊的錯誤檢查方法。 – 2010-06-29 15:09:04

+0

@Paul - 或者一個不錯的大'try ... catch(Exception)'...好吧,也許是一個更具體的異常類型的較小的一個,但你不必提前檢查它。 – 2010-06-29 21:52:16

1

您可以使用一些約定來保存自己的一些代碼。基本上,使用反射來創建您想要的任何控件的實例,並從XML傳入代碼。例如:

Activator.CreateInstance(xmlchild.Name, ...) 

只需填寫正確的位,許多代碼就會消失。

1

這聽起來像你正在尋找像泛型一樣的東西。

你可以做一些事情如下:

public static class ControlFactory 
{ 
    public static T CreateControl<T>() where T : Type, new() 
    { 
     return new T(); 
    } 
} 

我沒有測試此的代碼,但這樣我試,我會更新。

1

首先看到Activator類。然後,您可以將控件的類型名稱作爲屬性存儲在xml文件中,並使用Activator類根據存儲在當前xml元素(type =「fullTypeName」)的屬性中的值創建實例。

此外,如果涉及屬性,您可以考慮通過反射來設置基於屬性名稱創建的實例的屬性(例如,您有一個控件的實例 - 使用Activator類創建 - 並且您從頂端分配值xml屬性創建實例的Top屬性,您可以通過使用反射來獲取/設置)。

1

可以像其他人描述的那樣使用Reflection來直接從名稱構造控件。但是,如果XML文件是公開可見的,則此設計相當脆弱並且可能會引起安全問題,因爲可以基於文件中的文本在運行時構建任意控件類型。這可能不是您特定應用程序的問題。

我更喜歡使用Dictionary<string, Func<Control>>的設計,其中您的代碼註冊了一個爲每個名稱創建控件的回調。這爲您提供了一些額外的靈活性(您可以動態調換控制構建方法或合併來自多個來源的可用控件),並且也可以看起來更清晰(開關被幾個「註冊」調用取代,實際構造分解爲單獨的方法或(在簡單情況下)作爲lambda表達式)。如果使用MyImprovedTextBox替換應用程序中的TextBox並希望以前的配置文件使用改進版本,這也允許向後兼容。

相關問題