Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
113 views
in Technique[技术] by (71.8m points)

c# - need to split packet and distribute to the right owner based on rule match

I need to split a packet bases on some Rules and Name which I need to match with different list NameOwnersBasedOnRule.

I have a class NameOwnersBasedOnRule where I have defined my different set of RuleOwner for a Name, number of Rule and Owner are NOT fixed for each Name.

var nameOwnersBasedOnRule = new List<NameOwnersBasedOnRule>
        {
            new NameOwnersBasedOnRule
            {
                Name = "Name1", Owners = new List<KeyValuePair<string, string>>
                {
                    new KeyValuePair<string, string>("Rule1", "Owner1"),
                    new KeyValuePair<string, string>("Rule2", "Owner2"),
                    new KeyValuePair<string, string>("Rule3", "Owner3")
                }
            },
            new NameOwnersBasedOnRule
            {
                Name = "Name2", Owners = new List<KeyValuePair<string, string>>
                {
                    new KeyValuePair<string, string>("Rule2", "Owner2")
                }
            },
            new NameOwnersBasedOnRule
            {
                Name = "Name3", Owners = new List<KeyValuePair<string, string>>
                {
                    new KeyValuePair<string, string>("Rule1", "Owner1"),
                    new KeyValuePair<string, string>("Rule1", "Owner2"),
                    new KeyValuePair<string, string>("Rule1", "Owner3")
                }
            }
        };

I have list of packet and each packet has some Rule associates with it and the Name is part of nested InstanceData and may be repeated for multiple InstanceName. Here is one sample data packet,

var dataPacket = new Packet
        {
            Id = new Guid("2e08bd98-68eb-4358-8efb-9f2adedfb034"),
            Rules = new List<string> { "Rule1", "Rule2" },
            Results = new Result
            {
                ResultName = "ResultName1",
                Instances = new List<Instance>
                {
                    new Instance
                    {
                        InstanceName = "InstanceName1",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name1", Value = "V1"},
                            new InstanceData{Name = "Name2", Value = "V2"},
                            new InstanceData{Name = "Name3", Value = "V3"},
                            new InstanceData{Name = "Name4", Value = "V4"}
                        }
                    },
                    new Instance
                    {
                        InstanceName = "InstanceName2",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name1", Value = "V5"},
                            new InstanceData{Name = "Name2", Value = "V6"},
                            new InstanceData{Name = "Name3", Value = "V7"},
                            new InstanceData{Name = "Name4", Value = "V8"}
                        }
                    }
                }
            }
        };
  • This packet have more than one Name and I need to split it based on matching rule and name from List<NameOwnersBasedOnRule> and need to distribute the the associated owners.

For above data example packet I have 2 rules "Rule1", "Rule2", hence

  • Name1 should be distributed to Owner1 and Owner2.

  • Name2 only to Owner2.

  • Name3 to all owners Owner1, Owner2, Owner3

  • 'Name4` to NONE

Expected data for each owner should be like this,

var owner1Data = new Packet
        {
            Id = new Guid("2e08bd98-68eb-4358-8efb-9f2adedfb034"),
            Results = new Result
            {
                ResultName = "ResultName1",
                Instances = new List<Instance>
                {
                    new Instance
                    {
                        InstanceName = "InstanceName1",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name1", Value = "V1"},
                            new InstanceData{Name = "Name3", Value = "V3"}
                        }
                    },
                    new Instance
                    {
                        InstanceName = "InstanceName2",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name1", Value = "V5"},
                            new InstanceData{Name = "Name3", Value = "V7"}
                        }
                    }
                }
            }
        };

        var owner2Data = new Packet
        {
            Id = new Guid("2e08bd98-68eb-4358-8efb-9f2adedfb034"),
            Results = new Result
            {
                ResultName = "ResultName1",
                Instances = new List<Instance>
                {
                    new Instance
                    {
                        InstanceName = "InstanceName1",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name1", Value = "V1"},
                            new InstanceData{Name = "Name2", Value = "V2"},
                            new InstanceData{Name = "Name3", Value = "V3"}
                        }
                    },
                    new Instance
                    {
                        InstanceName = "InstanceName2",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name1", Value = "V5"},
                            new InstanceData{Name = "Name2", Value = "V6"},
                            new InstanceData{Name = "Name3", Value = "V7"},
                        }
                    }
                }
            }
        };

        var owner3Data = new Packet
        {
            Id = new Guid("2e08bd98-68eb-4358-8efb-9f2adedfb034"),
            Results = new Result
            {
                ResultName = "ResultName1",
                Instances = new List<Instance>
                {
                    new Instance
                    {
                        InstanceName = "InstanceName1",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name3", Value = "V3"}
                        }
                    },
                    new Instance
                    {
                        InstanceName = "InstanceName2",
                        InstanceDatas = new List<InstanceData>
                        {
                            new InstanceData{Name = "Name3", Value = "V7"}
                        }
                    }
                }
            }
        }; 

Here all the class structure I have,

public class NameOwnersBasedOnRule
{
    public string Name { get; set; }
    public List<KeyValuePair<string, string>> Owners { get; set; }
}

public class Packet
{
    public Guid Id { get; set; }
    public List<string> Rules { get; set; }
    public Result Results { get; set; }
}

public class Result
{
    public string ResultName { get; set; }
    public List<Instance> Instances { get; set; }
}

public class Instance
{
    public string InstanceName { get; set; }
    public List<InstanceData> InstanceDatas { get; set; }
}

public class InstanceData
{
    public string Name { get; set; }
    public string Value { get; set; }
}

Note -

This below method split my big packet by Name.

private static IEnumerable<Packet> SplitByName(Packet packet)
    {
        var names = packet.Results.Instances
            .SelectMany(it => it.InstanceDatas)
            .Select(it => it.Name)
            .Distinct()
            .ToList();

        IList<Packet> result = new List<Packet>();

        foreach (var name in names)
        {
            var newInstances = packet.Results.Instances
                .Select(it => new Instance
                {
                    InstanceName = it.InstanceName,
                    InstanceDatas = it.InstanceDatas
                        .Where(it1 => it1.Name == name)
                        .ToList()
                })
                .Where(it => it.InstanceDatas.Any())
                .ToList();

            var newResult = new Result
            {
                ResultName = packet.Results.ResultName,
                Instances = newInstances
            };

            result.Add(new Packet
            {
                Id = packet.Id,
                Results = newResult
            });
        }
        return result;
    }

Can we then prepare required result for each owner in one query?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use this method:

private Packet CreatePacket(string psOwner, Packet poSourcePacket, List<NameOwnersBasedOnRule> poRuleSet)
{
    //Create new Output Packet
    Packet loDestPacket = new Packet()
    {
        Id = poSourcePacket.Id,
        Results = new Result()
        {
            ResultName = poSourcePacket.Results.ResultName,
            Instances = new List<Instance>()
        }
    };

    //Create a simple List with valid Names for Owner and for all Rules in the Source
    IEnumerable<string> loList = poRuleSet
        .Where(item => item.Owners
            .Any(o => o.Value == psOwner && poSourcePacket.Rules.Contains(o.Key)))
        .Select(item => item.Name);

    //Add all Instance with InstanceData to the output Packet
    loDestPacket.Results.Instances.AddRange(poSourcePacket.Results.Instances
        .Where(item => item.InstanceDatas.Any(data => loList.Contains(data.Name)))
        .Select(item => new Instance()
        {
            InstanceName = item.InstanceName,
            InstanceDatas = new List<InstanceData>(item.InstanceDatas
                    .Where(data => loList.Contains(data.Name))
                    .Select(data => new InstanceData()
                    {
                        Name = data.Name,
                        Value = data.Value
                    }))
        }));

    return loDestPacket;
}

Call the method (for Owner1):

this.CreatePacket("Owner1", dataPacket, nameOwnersBasedOnRule);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...