Десериализация XML: возможно ли импортировать больше объектов, содержащих списки, где элементы списка являются одинаковыми объектами? - PullRequest
0 голосов
/ 16 мая 2019

Я сериализовал некоторые объекты, все объекты имеют список «LinkObject». Эти списки делятся некоторыми из этих «объектов ссылок». Если я десериализую, то все элементы списка будут независимы, это разные объекты.

I have a list of "OperationsObjects":
public class OperationObject
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }
        public string Physname { get; set; }
        public string JournalID { get; set; }
        public List<ParameterObject> ParameterObjectList = new List<ParameterObject>();
        public List<ConditionObject> ConditionObjectList = new List<ConditionObject>();
        public List<LinkObject> ChildLinkObjectList = new List<LinkObject>();
    }

public class LinkObject
    {
        public int? Number { get; set; }
        public string LogicType { get; set; }
        public string PrimaryID { get; set; }
        public string SecondaryID { get; set; }
    }

Если я сериализуюсь, то получу несколько похожих строк XML:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfOperationObjects xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OperationObjectList>
    <OperationObject Name="step forward">
      <ParameterObjectList />
      <ConditionObjectList />
      <ChildLinkObjectList>
        <LinkObject>
          <Number>0</Number>
          <LogicType>And</LogicType>
          <PrimaryID>GanttOperationObject[gantt_1]</PrimaryID>
          <SecondaryID>GanttOperationObject[gantt_2]</SecondaryID>
        </LinkObject>
        <LinkObject>
          <Number>2</Number>
          <LogicType>And</LogicType>
          <PrimaryID>GanttOperationObject[gantt_3]</PrimaryID>
          <SecondaryID>GanttOperationObject[gantt_1]</SecondaryID>
        </LinkObject>
      </ChildLinkObjectList>
      <Physname>Program-Parameters</Physname>
      <PhysType>NXOpen.Mechatronics.ProxyObject</PhysType>
      <Duration>2</Duration>
      <StartTime>1</StartTime>
      <OperationType>Simple</OperationType>
      <JournalID>GanttOperationObject[gantt_1]</JournalID>
    </OperationObject>
    <OperationObject Name="118 Component M8">
      <ParameterObjectList />
      <ConditionObjectList />
      <ChildLinkObjectList>
        <LinkObject>
          <Number>0</Number>
          <LogicType>And</LogicType>
          <PrimaryID>GanttOperationObject[gantt_1]</PrimaryID>
          <SecondaryID>GanttOperationObject[gantt_2]</SecondaryID>
        </LinkObject>
        <LinkObject>
          <Number>1</Number>
          <LogicType>And</LogicType>
          <PrimaryID>GanttOperationObject[gantt_2]</PrimaryID>
          <SecondaryID>GanttOperationObject[gantt_4]</SecondaryID>
        </LinkObject>
      </ChildLinkObjectList>
      <Duration>1</Duration>
      <StartTime>3</StartTime>
      <OperationType>Simple</OperationType>
      <JournalID>GanttOperationObject[gantt_2]</JournalID>
    </OperationObject>

Итак, я хочу иметь тот же объект для объектов LinkObject с номером 0. На самом деле я хочу отредактировать Linkobject в моем OperationObject Name = "шаг вперед", и я ожидаю, что LinkObject будет также отредактирован в OperationObject Name = "118 Component M8"

1 Ответ

1 голос
/ 16 мая 2019

Вы не можете сделать это автоматически. Но вы должны сделать это вручную после десериализации. Вы можете собрать все уникальные объекты LinkObject в отдельную коллекцию и заменить каждый связанный LinkObject на OperationObject из этой коллекции по Id (в вашем случае это значение Number).
Есть пример кода. Я использовал json сериализатор, но на самом деле это не имеет значения.

List<TestParent> parents = new List<TestParent>();
            TestChild child = new TestChild() { Name = "Test" };
            //add to parent class with the same child class;
            parents.Add(new TestParent() { Child = new List<TestChild>() { child } });
            parents.Add(new TestParent() { Child = new List<TestChild>() { child } });
            String data = JsonConvert.SerializeObject(parents);
            List<TestParent> deserializedData = JsonConvert.DeserializeObject<List<TestParent>>(data);
            var comparer = new ChildComparer();
            List<TestChild> brokenLinkCollection = deserializedData.SelectMany(x => x.Child).Distinct().ToList();
            // 2 Child with the same Name
            List<TestChild> uniqueCollection = deserializedData.SelectMany(x => x.Child).Distinct(comparer).ToList();

            var processedChild = deserializedData.Select(x => x.Child).ToList();

            processedChild.ForEach(x =>
            {
                var substitutedCollection = uniqueCollection.Where( uc => x.Contains(uc, comparer)).ToList(); 
                x.Clear();
                x.AddRange(substitutedCollection);
            });

            List<TestChild> resoredCollection = deserializedData.SelectMany(x => x.Child).Distinct().ToList();
            // 1 Child is found due to linking to one memory object

используемые классы:

 class ChildComparer : EqualityComparer<TestChild>
    {
        public override bool Equals(TestChild b1, TestChild b2)
        {
            if (b1 == null && b2 == null)
                return true;
            else if (b1 == null || b2 == null)
                return false;

            return (b1.Name == b2.Name);
        }
        public override int GetHashCode(TestChild bx)
        {
            return bx.Name.GetHashCode();
        }
    }
    public class TestChild
    {
        public string Name { set; get; }
    }
    public class TestParent
    {
        public List<TestChild> Child { set; get; }
    }
...