Skip to main content
4 of 5
added 2402 characters in body

Optimizing recursive reading of a UI configuration file

In our project(windows app, winforms) 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 file is designed for a complex UI, The UI has Frames, Frames can have Tabs, Tabs->Tabs-> finally one control to display the Content.

Following are two methods which are heavily used recursively. Their hit count is roughly 2000 or more times.

  1. DeserializeChildren
  2. DeserializeFrames

Inside these methods we have plain old nested, multiple for 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 call to DeserializeFrames this 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);

    }