I have large switch statement in which I create UIElements based on input value from XElement:
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;
}
}
I am creating a lot controls like this and as you can see, too much repetition is going on.
Is there some way to avoid this repetition? Thanks in advance for ideas.
A switch statement is usually more efficient than a set of nested ifs. Deciding whether to use if-then-else statements or a switch statement is based on readability and the expression that the statement is testing.
The biggest problem with switch statements, in general, is that they can be a code smell. Switch overuse might be a sign that you're failing to properly employ polymorphism in your code.
Disadvantages of switch statementsfloat constant cannot be used in the switch as well as in the case. You can not use the variable expression in case. You cannot use the same constant in two different cases. We cannot use the relational expression in case.
You could create a generic function that does the create:
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 }
}
Your switch then becomes:
switch (element.Attribute("Type").Value) {
case "System.Windows.Forms.Label" : return Create<System.Windows.Forms.Label>(name, text, width, height);
etc.
}
You could also adapt this to pass in the XElement, whichever you prefer.
If the Type attribute is always the name of the System.Type you want, then you could just do
Control ctrl = (Control) Activator.CreateInstance(Type.GetType(element.Attribute("Type").Value));
ctrl.Name = name;
etc.
If there's a one to one mapping between the value of the attribute and the type you want, then you can declare a readonly static field with the mapping:
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. }
};
And use
UIElement elem = (UIElement) Activator.CreateInstance(uiTypeMapping[element.Attribute("Type").Value]);
etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With