2010-06-29 81 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并希望以前的配置文件使用改进版本,这也允许向后兼容。

相关问题