首页 > 解决方案 > 从 POCO C# 中检索部分结构化数据

问题描述

我有一个List<TerminalLink>我想从中检索一个子集的。请参阅下面的类结构。

该子集由一个“地图”定义,该地图标识ChannelLink在任何给定场景中选择哪个。ChannelLink每个场景可能需要多个s,可能来自相同的 s ChannelGroup,可能来自相同的不同ChannelGroups TerminalLink,也可能来自我原始内存列表中的多个TerminalLinks。

只有在 ChannelGroupLink 和 TerminalLink 也匹配时才能选择 ChannelLink(我猜它们是索引的一部分)。

我尝试了各种 Linq 和 foreach 方法,但我遇到了数十行代码,这很难看且难以理解。我确信有一种优雅的方法。

如何返回List<TerminalLink>仅包含与我的地图匹配的数据的修剪(即仅包含TerminalLinksChannelGroupLinksrequired ChannelLinks)?

班级结构:

public class TerminalLink
{
    public string TerminalName { get; set; }
    public string TerminalType { get; set; }
    public ChannelGroupLink[] ChannelGroups { get; set; }
}

public class ChannelGroupLink
{
    public string GroupName { get; set; } 
    public int ItemType { get; set; }
    public int SubType { get; set; }
    public ChannelLink[] Channels { get; set; }
}

public class ChannelLink
{
    public string ChannelName { get; set; }
    public string PathName { get; set; }
    public string DataType { get; set; }
    public bool IsOutput { get; set; }
}

编辑以包括最新尝试:

public static List<TerminalLink> GetCompatibleChannelLinks(List<TerminalLinkMap> terminalLinkMaps, List<TerminalLink> asBuiltList)
{
    List<TerminalLink> matching = new List<TerminalLink>();

    var terminalsWithSomeMatchingChannelGroups = from terminal in asBuiltList
        from tlm in terminalLinkMaps
        where terminal.TerminalType == tlm.ItemSubTypeName
        from cgsMaps in tlm.ChannelGroupsToLink
        from cgs in terminal.ChannelGroups
        where cgsMaps.IsLinkMatch(cgs.GroupName, cgs.ItemType, cgs.SubType)
        select (
            link: new TerminalLink()
            {
                TerminalName = terminal.TerminalName,
                TerminalType = terminal.TerminalType
            },
            original: terminal, map: tlm
        );

    foreach (var possibleLink in terminalsWithSomeMatchingChannelGroups)
    {
        var linkCandidate = possibleLink.link;
        var originalData = possibleLink.original;
        var map = possibleLink.map;

        foreach (var cgs in originalData.ChannelGroups)
        {
            foreach (var channel in cgs.Channels)
            {
                // WIP
            }
        }
    }
}

编辑 2:包含 TerinalLinkMap

public class TerminalLinkMap
{
    public string TerminalTypeName { get; set; }
    public string ItemSubTypeName { get; set; } // Match on this.
    public ChannelGroupToLink[] ChannelGroupsToLink { get; set; }
}

public class ChannelGroupToLink
{
    public string GroupName { get; set; } // regex match is ok.
    public int ItemType { get; set; }
    public int SubType { get; set; }
    public ChannelToLink[] Channels { get; set; }
    public ChannelGroupToLink GetClone() => GetClone(this);

    public bool IsLinkMatch(string groupName, int itemType, int subType)
    {
        return
        GroupName == groupName
        && ItemType == itemType
        && SubType == subType;
    }
}

public class ChannelToLink
{
    public int ItemType { get; set; }
    public string DataType { get; set; }
    public int DataSizeInBits { get; set; }
    public bool IsOutput { get; set; }
    public ChannelToLink GetClone() => GetClone(this);

    public bool IsLinkMatch(string dataType, bool isOutput)
    {
        return
        DataType == dataType
        && IsOutput == isOutput;
    }

    public static ChannelToLink GetClone(ChannelToLink original) => new ChannelToLink()
    {
        ItemType = original.ItemType,
        DataType = original.DataType,
        DataSizeInBits = original.DataSizeInBits,
        IsOutput = original.IsOutput
    };
}

标签: c#linq

解决方案


没有必要加入。

尝试以下操作:

class Program
{
    static void Main(string[] args)
    {
        List<TerminalLink> asBuiltList = new List<TerminalLink>();

        List<TerminalLink> links = asBuiltList
                .Select(x => new { TerminalLink = x, ChannelGroups = x.ChannelGroups.Where(y => y.IsLinkMatch("Apple", 123, 456)) })
                .Where(x => x.ChannelGroups.Count() > 0)
                .Select(x => new TerminalLink() { TerminalName = x.TerminalLink.TerminalName, TerminalType = x.TerminalLink.TerminalType, ChannelGroups = x.ChannelGroups.ToArray()})
                .ToList(); 
        }
    }
    public class TerminalLink
    {
        public string TerminalName { get; set; }
        public string TerminalType { get; set; }
        public ChannelGroupLink[] ChannelGroups { get; set; }
    }

    public class ChannelGroupLink
    {
        public string GroupName { get; set; }
        public int ItemType { get; set; }
        public int SubType { get; set; }
        public ChannelLink[] Channels { get; set; }

        public Boolean IsLinkMatch(string groupName, int itemType, int subType)
        {
            return (this.GroupName == groupName) && ( this.ItemType == itemType) && (this.SubType == subType);
        }
    }

    public class ChannelLink
    {
        public string ChannelName { get; set; }
        public string PathName { get; set; }
        public string DataType { get; set; }
        public bool IsOutput { get; set; }
    }
}

推荐阅读