0

I have a C# winforms application. In this application I am creating a list of CanMessage objects dynamically from an xml file.

The xml file is constructed as below

<message id="0x641" ecu="BCM" name="BODY9" dlc="8" cyclicrate="500">
<bytes>
  <byte0>0x0</byte0>
  <byte1>0x0</byte1>
  <byte2>0x0</byte2>
  <byte3>0x0</byte3>
  <byte4>0x0</byte4>
  <byte5>0x0</byte5>
  <byte6>0x0</byte6>
  <byte7>0x0</byte7>
</bytes>

The Canmessage object is constructed like this:

CanMessage(String name,String _EcuName, ulong id, ushort dlc,int[] bytearray , int cyclic)
    {

        this.Name = name;
        this.EcuName = _EcuName;
        this.Id = id;
        this.Dlc = dlc;
        this.Bytes = new int[dlc];
        this.CyclicRate = cyclic;
        int i = 0;
        for(i = 0; i < dlc; i++)
        {
            this.Bytes[i] = bytearray[i];
        }
    }

Below is how I am building my Canmessage list:

public void BuildCanList()
    {
        try
        {
            XmlDocument xd = new XmlDocument();
            xd.Load(XmlFile);

            XmlNodeList nodelist = xd.SelectNodes("/messages/message");

            foreach (XmlNode n in nodelist)
            {
                String name, ecuname;
                ulong id;
                ushort dlc;
                int[] bytes = new int[Convert.ToInt32(n.Attributes.GetNamedItem("dlc").Value)];
                int cyclic;

                name = n.Attributes.GetNamedItem("name").Value.ToString();
                id = (ulong)Convert.ToInt32(n.Attributes.GetNamedItem("id").Value, 16);
                ecuname = n.Attributes.GetNamedItem("ecu").Value.ToString();
                dlc = (ushort)Convert.ToByte(n.Attributes.GetNamedItem("dlc").Value);
                cyclic = Convert.ToInt32(n.Attributes.GetNamedItem("cyclicrate").Value);
                XmlNode sn = n.SelectSingleNode("bytes");
                for (ushort i = 0; i < dlc; i++)
                {
                    try
                    {
                        bytes[i] = Convert.ToInt32(sn.ChildNodes.Item(i).InnerText, 16);
                    }
                    catch(Exception e)
                    {
                        bytes[i] = 0x0;
                        Console.WriteLine(String.Format("Error Building can Message: {0}", e.ToString()));
                    }

                }
                CanMessage cm = new CanMessage(name, ecuname, id, dlc, bytes, cyclic);
                CanList.Add(cm);
            }

My list is being created with no issues. My question is after my list has been created I will sometimes need to do some bit manipulation on certain bytes of a certain Canmessage. How can I select a message from the list based on its name property and then edit certain bytes from that message? I know how to select a message from the list using lambda expression and linq. But I don't know how to then combine that select method with an edit and save method or if this is even the best way to go about doing this.

Jubin Justifies
  • 397
  • 4
  • 12
pleslie
  • 87
  • 7
  • What do you mean? Note that you could use a dictionary in order to go directly to your object with a name (key-value pair). From there you would get the value and then you could edit it as usual without a `linq` expression. – Nordes Jan 06 '20 at 03:57
  • In case you don't know, you can also use a Lookup and have 1 key with multiple values (in case you have 1 name appearing multiple time) – Nordes Jan 06 '20 at 04:06
  • Reading from xml into object is **deserialization**. Then you can edit the list as any list. Saving would be **serialization**. See [this answer](https://stackoverflow.com/questions/42708070/how-do-i-create-a-dto-in-c-sharp-asp-net-from-a-fairly-complex-json-response) for serialization and deserialization and editing will be simply the same as editing any list or object. – CodingYoshi Jan 06 '20 at 04:17
  • 1
    1) deserialize 2) edit in memory 3) serialize. Or edit XML file directly. – CodingYoshi Jan 06 '20 at 04:19

1 Answers1

1

If i understand your problem statement correctly, you need to find a specific CanMessage in the List<CanMessage> and edit its properties to your liking. Since your CanMessage is an object, it's being accessed by reference and therefore your edits will get reflected everywhere you reference it from.

Consider the following:

{
    var CanList = new List<CanMessage>(); // I am assuming this is what it is
    BuildCanList(CanList);

    var messagetoEdit = CanList.First(m => m.Name == "BODY9");
    messagetoEdit.Bytes[1]= 0xff;
    messagetoEdit.Bytes[2]= 0xff;
    messagetoEdit.Bytes[3]= 0xff;
    messagetoEdit.Bytes[4]= 0xff;

    var newMessagetoEdit = CanList.First(m => m.Name == "BODY9"); // you will see that values have changed here

    //in case you wanted to serialise the list back, heres a snippet on how you could do it, for more details see https://stackoverflow.com/questions/6161159/converting-xml-to-string-using-c-sharp
    //this is just to prove a point that changing bytes has effect, 
    StringWriter sw = new StringWriter();   
    var serialiser = new XmlSerializer(typeof(List<CanMessage>));
    serialiser.Serialize(sw, CanList);
    sw.ToString();
}

I hope this clarifies

timur
  • 14,239
  • 2
  • 11
  • 32