优化大型switch语句

Val*_*ale 5 c# .net-4.0 switch-statement

我有一个大的switch语句,我根据XElement的输入值创建UIElements:

public static UIElement CreateElement(XElement element) {
            var name = element.Attribute("Name").Value;
            var text = element.Attribute("Value").Value;
            var width = Convert.ToDouble(element.Attribute("Width").Value);
            var height = Convert.ToDouble(element.Attribute("Height").Value);
            //...
            switch (element.Attribute("Type").Value) {
                case "System.Windows.Forms.Label":
                    return new System.Windows.Controls.Label() {
                        Name = name,
                        Content = text,
                        Width = width,
                        Height = height
                    };
                case "System.Windows.Forms.Button":
                    return new System.Windows.Controls.Button() {
                        Name = name,
                        Content = text,
                        Width = width,
                        Height = height
                    };
                    //...
                default:
                    return null;
            }
        }
Run Code Online (Sandbox Code Playgroud)

我正在创建这样的很多控件,正如你所看到的,重复过多.

有没有办法避免这种重复?提前感谢您的想法.

Fly*_*179 6

您可以创建一个执行创建的泛型函数:

private static Create<T>(string name, string text, double width, double height) where T: Control, new()
{
   return new T { Name = name, Content = text, Width = width, Height = height }
}
Run Code Online (Sandbox Code Playgroud)

您的交换机将变为:

switch (element.Attribute("Type").Value) {
  case "System.Windows.Forms.Label" : return Create<System.Windows.Forms.Label>(name, text, width, height);
  etc.
}
Run Code Online (Sandbox Code Playgroud)

你也可以调整它来传递XElement,无论你喜欢什么.

如果Type属性始终是您想要的System.Type的名称,那么您可以这样做

Control ctrl = (Control) Activator.CreateInstance(Type.GetType(element.Attribute("Type").Value));
ctrl.Name = name;
etc.
Run Code Online (Sandbox Code Playgroud)

如果属性值与所需类型之间存在一对一映射,则可以使用映射声明只读静态字段:

private static readonly uiTypeMapping = new Dictionary<string,Type> {
  { "System.Windows.Forms.Label", typeof(System.Windows.Controls.Label) },
  { "System.Windows.Forms.Button", typeof(System.Windows.Controls.Button) },
  { etc. }
};
Run Code Online (Sandbox Code Playgroud)

并使用

UIElement elem = (UIElement) Activator.CreateInstance(uiTypeMapping[element.Attribute("Type").Value]);
etc.
Run Code Online (Sandbox Code Playgroud)


All*_*est 6

像这样的东西可以工作...... :)

var controlCreators = new Dictionary<string, Func<ContentControl>>
                        {
                            {"System.Windows.Forms.Label", () => new Label()},
                            {"System.Windows.Forms.Button", () => new Button()}
                        };

Func<ContentControl> createControl;
if (!controlCreators.TryGetValue(element.Attribute("Type").Value, out createControl))
{
    return null;
}

var control = createControl();
control.Name = name;
control.Content = text;
control.Width = width;
control.Height = height;
return control;
Run Code Online (Sandbox Code Playgroud)