In our project (windowsWindows app, winformsWinforms), the UI is designed based on XML configuration file. I have a program to read the UI configuration file and Parse the configuration and design the UI. The Configuration
The configuration file is designed for a complex UI,. The UI has FramesFrame
s, Framesand Frame
s can have Tabs, Tabs->Tabs-> finally one control to display the Contentcontent.
- DeserializeChildren
DeserializeChildren
- DeserializeFrames
DeserializeFrames
Inside these methods we have plain old nested, multiple forfor
loops. I try to refactor these methods but I couldn't find any alternative way to do the program other than what it is currently.
So I am posting to experts who can suggest me to refactor it.
private void DeserializeChildren(WindowConfig config, string parent)
{
if (config.Frame.ChildControls == null)
{
config.Frame.ChildControls = DeserializeFrames(parent);
}
if (config.Commands == null)
{
config.Commands = DeserializeCommands(parent);
}
List<SerializerContainer> scList = list.FindAll(sc => (sc.Parent == parent) &&
(sc.Processed == false) &&
(sc.ConfigType == WINDOWCONFIG));
List<WindowConfig> wcList = new List<WindowConfig>();
scList = ListSort(scList);
foreach (SerializerContainer sc in scList)
{
string nextParent = sc.Name;
WindowConfig windowConfig; // = new WindowConfig();
windowConfig = DeserializeIt<WindowConfig>(sc.Config);
sc.Processed = true;
wcList.Add(windowConfig);
DeserializeChildren(windowConfig, parent + nextParent);
}
if (wcList.Count > 0)
{
config.ChildWindows = wcList.ToArray();
}
return;
}
The above code has a call to DeserializeFrames thisDeserializeFrames
, which is again a recursive method.
private ControlItemConfig[] DeserializeFrames(string parent)
{
List<SerializerContainer> scList = list.FindAll(sc => (sc.Parent == parent) &&
(sc.Processed == false) &&
(sc.ConfigType == CONTROLITEMCONFIG));
List<ControlItemConfig> cicList = new List<ControlItemConfig>();
scList = ListSort(scList);
foreach (SerializerContainer sc in scList)
{
ControlItemConfig itemConfig; // = new ControlItemConfig();
itemConfig = DeserializeIt<ControlItemConfig>(sc.Config);
sc.Processed = true;
cicList.Add(itemConfig);
if ((itemConfig.Type == ControlType.Frame))
{
var frameConfig = (FrameConfig)itemConfig.Instance;
if (frameConfig.ChildControls == null)
{
frameConfig.ChildControls = DeserializeFrames(sc.Parent + sc.Name);
}
}
}
return cicList.ToArray();
}
Other smaller methods involved are:
private CommandConfig[] DeserializeCommands(string parent)
{
List<SerializerContainer> scList = list.FindAll(sc => (sc.Parent == parent) &&
(sc.Processed == false) &&
(sc.ConfigType == COMMANDCONFIG));
List<CommandConfig> ccList = new List<CommandConfig>();
scList = ListSort(scList);
foreach (SerializerContainer sc in scList)
{
CommandConfig commandConfig;
commandConfig = DeserializeIt<CommandConfig>(sc.Config);
sc.Processed = true;
ccList.Add(commandConfig);
}
return ccList.ToArray();
}
private VariableConfig[] DeserializeSortedVariables(string parent)
{
List<SerializerContainer> scList = list.FindAll(sc => (sc.Parent == parent) &&
(sc.Processed == false) &&
(sc.ConfigType == VARIABLECONFIG));
List<VariableConfig> ccList = new List<VariableConfig>();
scList = ListSort(scList);
foreach (SerializerContainer sc in scList)
{
VariableConfig variableConfig;
variableConfig = DeserializeIt<VariableConfig>(sc.Config);
sc.Processed = true;
ccList.Add(variableConfig);
}
return ccList.ToArray();
}
private List<SerializerContainer> ListSort(List<SerializerContainer> listParam)
{
List<SerializerContainer> imList = listParam.FindAll(sc => (sc.Source == "XXX"));
List<SerializerContainer> dmList = listParam.FindAll(sc => (sc.Source == "YYY"));
imList.Sort();
dmList.Sort();
SerializerContainer[] scArray = new SerializerContainer[listParam.Count];
//the goal is to use the absolute position value for XXX as set by
//each node's order value. after processing the XXX, process the yyyy data,
//plugging nodes into the array being built in the first open position found starting from
//the front of the array
//iterate through the instrument manager's configuration list from end to start
int idx;
for (int i = imList.Count - 1; i >= 0; i--)
{
//if the config node's order is greater than the number of elements in overall list
//set the index to the point to the last element in the array we are populating;
//otherwise set the index to the node's order value.
if (imList[i].Order >= listParam.Count)
{
idx = listParam.Count - 1;
}
else
{
idx = imList[i].Order - 1;
}
//find a spot in the array that is not occupied and put the node there.
while (scArray[idx] != null)
{
idx--;
}
if (idx >= 0)
{
scArray[idx] = imList[i];
}
else
{
throw new ArgumentOutOfRangeException(@"The index for the configuration list sort operation is less than zero.");
}
}
idx = 0;
//plug im nodes in wherever we find an open spot in the array
foreach (SerializerContainer sc in dmList)
{
while (scArray[idx] != null)
{
idx++;
}
scArray[idx] = sc;
}
return new List<SerializerContainer>(scArray);
}