Как упростить несколько вложенных циклов foreach? - PullRequest
0 голосов
/ 07 ноября 2018
 private DataTable GetAttributeTable()
    {
        DataTable cltAttributeTable = new DataTable("CLT_ATTRIBUTE");
        DataColumnCollection iRefColumns = cltAttributeTable.Columns;
        //BETHiddenColumn is defined for hiding certain columns at the UI
        //And can be used for manipulating entities internally
        iRefColumns.AddRange(new[]
        {
            new BETHiddenColumn { ColumnName = CLDConstants.CLTGUID, DataType = typeof(string), ReadOnly = true },
            new DataColumn { ColumnName = CLDConstants.CLTNAME, DataType = typeof(string), ReadOnly = true },
            new BETHiddenColumn { ColumnName = CLDConstants.SHEETID, DataType = typeof(string), ReadOnly = true },
            new DataColumn { ColumnName = CLDConstants.SHEETNAME, DataType = typeof(string), ReadOnly = true },
            new DataColumn { ColumnName = "OBJECT_TYPE", DataType = typeof(string), ReadOnly = true },
            new DataColumn { ColumnName = "OBJECT_NAME", DataType = typeof(string), ReadOnly = true },
            new DataColumn { ColumnName = "ATTRIBUTE_NAME", DataType = typeof(string), ReadOnly = true },
            new DataColumn { ColumnName = "ATTRIBUTE_VALUE", DataType = typeof(string), ReadOnly = false }
        });
        return cltAttributeTable;
    }

public override async Task<DataTable> GetDataAsync(ControlNetworkStructure controlNetwork)
    {
        DataTable cltAttributeTable = GetAttributeTable();
        try
        {
            using (var automationService = ConsumedServiceProvider.Provider.AutomationService)
            {
                foreach (string userDefinedLogicTemplate in selectedCLT)
                {
                    var controlLogicClt =
                        automationService.AutomationClt.GetControlLogicTemplate(userDefinedLogicTemplate);
                    foreach (ISheet sheet in await controlLogicClt.GetSheets())
                    {

                        foreach (IFunctionCode functionCode in await sheet.GetFunctionCodes())
                        {
                            foreach (IHarmonyAttribute functionCodeAttribute in functionCode.Attributes)
                            {

                                DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
                                row["OBJECT_TYPE"] = "FUNCTION CODE";
                                row["OBJECT_NAME"] = functionCode.Name;
                                row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
                                row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
                                cltAttributeTable.Rows.Add(row);
                            }
                        }

                        foreach (IInputReference inputReference in await sheet.GetInputReferences())
                        {
                            foreach (IHarmonyAttribute functionCodeAttribute in inputReference.Attributes)
                            {

                                DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
                                row["OBJECT_TYPE"] = "IREF";
                                row["OBJECT_NAME"] = inputReference.Name;
                                row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
                                row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
                                cltAttributeTable.Rows.Add(row);
                            }
                        }

                        foreach (IOutputReference outputReference in await sheet.GetOutputReferences())
                        {
                            foreach (IHarmonyAttribute functionCodeAttribute in outputReference.Attributes)
                            {

                                DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
                                row["OBJECT_TYPE"] = "OREF";
                                row["OBJECT_NAME"] = outputReference.Name;
                                row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
                                row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
                                cltAttributeTable.Rows.Add(row);
                            }
                        }

                        foreach (IText text in await sheet.GetTexts())
                        {
                            foreach (IHarmonyAttribute functionCodeAttribute in text.Attributes)
                            {

                                DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
                                row["OBJECT_TYPE"] = "TEXT";
                                row["OBJECT_NAME"] = text.Name;
                                row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
                                row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
                                cltAttributeTable.Rows.Add(row);
                            }
                        }


                    }
                }
            }
        }
        catch (Exception exception)
        {
            LogService.LogException(this, ServiceResources.CONTEXT_CLD_EDITOR, "CLT Attribute",
                exception);
        }
        finally
        {
            // Accepting all the modification to the table before leaving this method call
            cltAttributeTable.AcceptChanges();
        }
        return cltAttributeTable;
    }

Описание

У меня есть метод с несколькими циклами foreach внутри, и мне трудно понять его, поскольку я новичок в C #. Также я прочитал, что не рекомендуется писать несколько циклов foreach в программе. Метод возвращает таблицу данных, и она связана с сетью данных. Может кто-нибудь помочь мне упростить его, чтобы он стал лучше читаемым и интуитивно понятным?

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Хорошо, это довольно поспешно, но я думаю, что это хорошее начало. У меня не было времени, чтобы проверить это, поэтому, вероятно, есть некоторые ошибки. Также есть много возможностей для улучшений.

private DataTable GetAttributeTable()
{
    DataTable cltAttributeTable = new DataTable("CLT_ATTRIBUTE");
    DataColumnCollection iRefColumns = cltAttributeTable.Columns;
    //BETHiddenColumn is defined for hiding certain columns at the UI
    //And can be used for manipulating entities internally
    iRefColumns.AddRange(new[]
    {
        new BETHiddenColumn { ColumnName = CLDConstants.CLTGUID, DataType = typeof(string), ReadOnly = true },
        new DataColumn { ColumnName = CLDConstants.CLTNAME, DataType = typeof(string), ReadOnly = true },
        new BETHiddenColumn { ColumnName = CLDConstants.SHEETID, DataType = typeof(string), ReadOnly = true },
        new DataColumn { ColumnName = CLDConstants.SHEETNAME, DataType = typeof(string), ReadOnly = true },
        new DataColumn { ColumnName = "OBJECT_TYPE", DataType = typeof(string), ReadOnly = true },
        new DataColumn { ColumnName = "OBJECT_NAME", DataType = typeof(string), ReadOnly = true },
        new DataColumn { ColumnName = "ATTRIBUTE_NAME", DataType = typeof(string), ReadOnly = true },
        new DataColumn { ColumnName = "ATTRIBUTE_VALUE", DataType = typeof(string), ReadOnly = false }
    });
    return cltAttributeTable;
}

public override async Task<DataTable> GetDataAsync(ControlNetworkStructure controlNetwork)
{
    DataTable cltAttributeTable = new DataTable();
    try
    {
        using (var automationService = ConsumedServiceProvider.Provider.AutomationService)
        {
            foreach (string userDefinedLogicTemplate in selectedCLT)
            {
                var controlLogicClt =
                    automationService.AutomationClt.GetControlLogicTemplate(userDefinedLogicTemplate);

                cltAttributeTable = await LoopDeLoop(controlLogicClt);
            }
        }
    }
    catch (Exception exception)
    {
        LogService.LogException(this, ServiceResources.CONTEXT_CLD_EDITOR, "CLT Attribute",
            exception);
    }
    finally
    {
        // Accepting all the modification to the table before leaving this method call
        cltAttributeTable.AcceptChanges();
    }
    return cltAttributeTable;
}

//Main loop with loops adding rows
private async Task<DataTable> LoopDeLoop(dynamic controlLogicClt)
{
    DataTable cltAttributeTable = GetAttributeTable();

    foreach (ISheet sheet in await controlLogicClt.GetSheets())
    {
        foreach (IFunctionCode functionCode in await sheet.GetFunctionCodes())
        {
            cltAttributeTable = GetNewRows(cltAttributeTable, functionCode.Attributes, functionCode.Name, "FUNCTION CODE", controlLogicClt, sheet);
        }

        foreach (IInputReference inputReference in await sheet.GetInputReferences())
        {
            cltAttributeTable = GetNewRows(cltAttributeTable, inputReference.Attributes, inputReference.Name, "IREF", controlLogicClt, sheet);
        }

        foreach (IOutputReference outputReference in await sheet.GetOutputReferences())
        {                           
            cltAttributeTable = GetNewRows(cltAttributeTable, outputReference.Attributes, outputReference.Name, "OREF", controlLogicClt, sheet);                        
        }

        foreach (IText text in await sheet.GetTexts())
        {
            cltAttributeTable = GetNewRows(cltAttributeTable, text.Attributes, text.Name, "TEXT", controlLogicClt, sheet);
        }
    }
}

//Adds the new created rows to the DataTable
private DataTable GetNewRows(DataTable cltAttributeTable, List<IHarmonyAttribute> attributes, string name, string objectType, dynamic controlLogicClt, ISheet sheet)
{
    foreach (IHarmonyAttribute attribute in attributes)
    {
        cltAttributeTable.Rows.Add(GetNewRow(sourceDataRow, attribute, name, objectType, controlLogicClt, sheet));
    }
}

//Creates and populates the new row
private DateRow GetNewRow(IHarmonyAttribute attribute, string name, string objectType, dynamic controlLogicClt, ISheet sheet)
{
        DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
        row["OBJECT_TYPE"] = objectType;
        row["OBJECT_NAME"] = name;
        row["ATTRIBUTE_NAME"] = attribute.Type;
        row["ATTRIBUTE_VALUE"] = attribute.Value;   

        return row;         
}

Итак, я сделал еще три метода:

LoopDeLoop -> Это для того, чтобы убрать из основного метода большинство циклов и сделать его более понятным. Кроме того, это делает петли sheets более четкими.

´GetNewRows´ -> Этот предназначен для создания общего цикла IHarmonyAttribute и избавления от необходимости использования четырех циклов.

GetNewRow -> Этот просто заполняет новый ряд, но теперь вам не нужно делать это четыре раза.

Надеюсь, это поможет

0 голосов
/ 07 ноября 2018

если свойство Attribute IFunctionCode, IInputReference и т. Д. Основано на общем интерфейсе, вы можете сделать что-то вроде этого:

List<ICommomInterface> items = new List<ICommomInterface>();
items.AddRange(await sheet.GetFunctionCodes());
items.AddRange(await sheet.GetInputReferences());
items.AddRange(await sheet.GetOutputReferences());
items.AddRange(await sheet.GetTexts());

items.foreach(item =>
{
    item.Attributes.ForEach(attrib =>
    {
        DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
        if(item is IFunctionCode){
            row["OBJECT_TYPE"] = "FUNCTION CODE";
        } else if(_other types_)
        {
        }
        row["OBJECT_NAME"] = item.Name;
        row["ATTRIBUTE_NAME"] = attrib.Type;
        row["ATTRIBUTE_VALUE"] = attrib.Value;
        cltAttributeTable.Rows.Add(row);
    });
});

Если это ваше намерение. Если они не используют общий базовый интерфейс, вы должны использовать класс объектов для списка и расширить if (item is IFunctionCode) {... check.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...