Наследование в c#

Есть класс, нужен немного другой класс, в котором добавлена одна строка в подкласс, как это реализовать? Вот пример моей неудачной реализации:

public class A
{
    public class Subclass1
    {
        string s = "";
        public class Subclass2
        {
        }
        public class Subclass3
        {
        }

        public Subclass1()
        {
            Subclass2 subclass2 = new Subclass2();
            Subclass3 subclass3 = new Subclass3();
        }
    }
}

public class B : A
{
    public class Subclass2 : A.Subclass1.Subclass2
    {
        public string s { get; set; }
    }
}

Вот немного подробнее

 public class A
        {
            public Subclass1 subclass1;
            public class Subclass1
            {
                public string s = "";
                public Subclass2 subclass2;
                public Subclass3 subclass3;
                public class Subclass2
                {
                    public string id;
                }
                public class Subclass3
                {
                }

                public Subclass1()
                {
                    subclass2 = new Subclass2();
                    subclass3 = new Subclass3();
                }
            }

                public A()
            {
                   subclass1 = new Subclass1();

            }

        }

        public class B : A
        {
            public class Subclass2 : A.Subclass1.Subclass2
            {
                public string s { get; set; }
            }
        }



main
{
 A a = new A();
 B b = new B();
 a.subclass1.subclass2.id = "23";//всё ок
 b.subclass1.subclass2.s = "asd";//не существует s,ошибка 
}

Вот схема XML

<?xml version="1.0" encoding="windows-1251"?>
<OPLIST FILENAME="123" NRECORDS="1" PRZCOD="004" SMOCOD="11002" VERS="2.2">
  <OP>
    <N_REC>123</N_REC>
    <TIP_OP>132</TIP_OP>
    <PERSON>
      <FAM>ИВАНОВ</FAM>
      <IM>ИВАН</IM>
      <OT>ИВАНОВИЧ</OT>
      <W>2</W>
      <DR>1954-08-03</DR>
      <MR>СТРОКА</MR>
      <C_OKSM>СТРОКА</C_OKSM>
      <SS>СТРОКА</SS>
      <KATEG>СТРОКА</KATEG>
      <PHONE>СТРОКА</PHONE>
    </PERSON>
    <ADDRES_G>
      <BOMG>0</BOMG>
      <FIAS_AOID>СТРОКА</FIAS_AOID>
      <FIAS_HOUSEID>СТРОКА</FIAS_HOUSEID>
      <SUBJ>СТРОКА</SUBJ>
      <OKATO>СТРОКА</OKATO>
      <RNNAME>СТРОКА</RNNAME>
      <NPNAME>СТРОКА</NPNAME>
      <UL>СТРОКА</UL>
      <DOM>СТРОКА</DOM>
      <KV>СТРОКА</KV>
      <DREG>1998-04-06</DREG>
    </ADDRES_G>
    <VIZIT>
      <DVIZIT>2020-01-28</DVIZIT>
      <METHOD>1</METHOD>
      <PETITION>0</PETITION>
      <RSMO>3</RSMO>
      <FPOLIS>1</FPOLIS>
      <VS_FORM>1</VS_FORM>
    </VIZIT>
    <INSURANCE>
      <TER_ST>СТРОКА</TER_ST>
      <ENP>СТРОКА</ENP>
      <OGRNSMO>СТРОКА</OGRNSMO>
      <POLIS>
        <VPOLIS>СТРОКА</VPOLIS>
        <NPOLIS>СТРОКА</NPOLIS>
        <DBEG>2020-01-28</DBEG>
      </POLIS>
      <ERP>СТРОКА</ERP>
    </INSURANCE>
    <DOC_LIST>
      <DOC>
        <DOCTYPE>СТРОКА</DOCTYPE>
        <DOCSER>СТРОКА</DOCSER>
        <DOCNUM>СТРОКА</DOCNUM>
        <DOCDATE>2003-10-10</DOCDATE>
        <NAME_VP>СТРОКА</NAME_VP>
      </DOC>
    </DOC_LIST>
  </OP>
</OPLIST>

            [Serializable]
            [XmlRoot("OPLIST")]
            public class OPLIST
            {
                [XmlAttribute("FILENAME")]
                public string Filename { get; set; }

                [XmlAttribute("NRECORDS")]
                public string Nrecords { get; set; }

                [XmlAttribute("PRZCOD")]
                public string Przcod { get; set; }

                [XmlAttribute("SMOCOD")]
                public string Smocod { get; set; }

                [XmlAttribute("VERS")]
                public string Vers { get; set; }

                [XmlElement("OP")]
                public List<OP> Op { get; set; }
                public OPLIST()
                {
                    Op = new List<OP>();
                }

            }


        public class OP
        {
            [XmlElement("N_REC")]
            public string N_rec { get; set; }

            [XmlElement("ID")]
            public string Id { get; set; }

            [XmlElement("TIP_OP")]
            public string Tip_op { get; set; }

            [XmlElement("PERSON")]
            public PERSON Person { get; set; }

            [XmlElement("OLD_PERSON")]
            public OLD_PERSON Old_person { get; set; }

            [XmlElement("ADDRES_G")]
            public ADDRES_G Addres_g { get; set; }


            [XmlElement("ADDRES_P")]
            public ADDRES_P Addres_p { get; set; }

            [XmlElement("VIZIT")]
            public VIZIT Vizit { get; set; }

            [XmlElement("INSURANCE")]
            public INSURANCE Insurance { get; set; }


            [XmlElement("PERSONB")]
            public List<PERSONB> Personb { get; set; }

            [XmlElement("DOC_LIST")]
            public DOC_LIST Doc_list { get; set; }

            [XmlElement("OLDDOC_LIST")]
            public OLDDOC_LIST Olddoc_list { get; set; }

            public OP()
            {
                Person = new PERSON();
                Old_person = new OLD_PERSON();
                Addres_g = new ADDRES_G();
                Addres_p = new ADDRES_P();
                Vizit = new VIZIT();
                Insurance = new INSURANCE();
                Personb = new List<PERSONB>();
                Doc_list = new DOC_LIST();
                Olddoc_list = new OLDDOC_LIST();

            }
        }


        public class OLDDOC_LIST
        {
            [XmlElement("OLD_DOC")]
            public List<OLD_DOC> Old_doc { get; set; }
            public OLDDOC_LIST()
            {
                Old_doc = new List<OLD_DOC>();
            }
        }


        public class DOC_LIST
        {
            [XmlElement("DOC")]
            public List<DOC> Doc { get; set; }
            public DOC_LIST()
            {
                Doc = new List<DOC>();
            }
        }

        public class OLD_DOC
        {
            [XmlElement("DOCTYPE")]
            public string Doctype { get; set; }

            [XmlElement("DOCSER")]
            public string Docser { get; set; }

            [XmlElement("DOCNUM")]
            public string Docnum { get; set; }

            [XmlElement("DOCDATE")]
            public string Docdate { get; set; }

            [XmlElement("DOCEXP")]
            public string Docexp { get; set; }

            [XmlElement("NAME_VP")]
            public string Name_vp { get; set; }
        }


        public class DOC
        {
            [XmlElement("DOCTYPE")]
            public string Doctype { get; set; }

            [XmlElement("DOCSER")]
            public string Docser { get; set; }

            [XmlElement("DOCNUM")]
            public string Docnum { get; set; }

            [XmlElement("DOCDATE")]
            public string Docdate { get; set; }

            [XmlElement("DOCEXP")]
            public string Docexp { get; set; }

            [XmlElement("NAME_VP")]
            public string Name_vp { get; set; }
        }

        public class PERSONB
        {
            [XmlElement("TYPE")]
            public string Type { get; set; }

            [XmlElement("PHOTO")]
            public string Photo { get; set; }
        }

        public class INSURANCE
        {
            [XmlElement("TER_ST")]
            public string Ter_st { get; set; }

            [XmlElement("ENP")]
            public string Enp { get; set; }

            [XmlElement("OGRNSMO")]
            public string Ogrnsmo { get; set; }

            [XmlElement("POLIS")]
            public List<POLIS> Polis { get; set; }

            [XmlElement("ERP")]
            public string Erp { get; set; }

            [XmlElement("ORDERZ")]
            public ORDERZ Orderz { get; set; }

            public INSURANCE()
            {
                Polis = new List<POLIS>();
                Orderz = new ORDERZ();
            }
        }


        public class POLIS
        {
            [XmlElement("VPOLIS")]
            public string Vpolis { get; set; }

            [XmlElement("NPOLIS")]
            public string Npolis { get; set; }

            [XmlElement("SPOLIS")]
            public string Spolis { get; set; }

            [XmlElement("DBEG")]
            public string Dbeg { get; set; }

            [XmlElement("DEND")]
            public string Dend { get; set; }

            [XmlElement("DSTOP")]
            public string Dstop { get; set; }
        }

        public class ORDERZ
        {
            [XmlElement("NORDER")]
            public string Norder { get; set; }

            [XmlElement("DORDER")]
            public string Dorder { get; set; }
        }


        public class VIZIT
        {
            [XmlElement("DVIZIT")]
            public string Dvizit { get; set; }

            [XmlElement("METHOD")]
            public string Method { get; set; }

            [XmlElement("PETITION")]
            public string Petition { get; set; }

            [XmlElement("RSMO")]
            public string Rsmo { get; set; }

            [XmlElement("RPOLIS")]
            public string Rpolis { get; set; }

            [XmlElement("FPOLIS")]
            public string Fpolis { get; set; }

            /*
             [XmlElement("VS_FORM")]
             public string Vsforms { get; set; }
             public bool ShouldSerializeVsforms() { return Vsforms != ""; }
             */
        }


        public class ADDRES_P
        {

            [XmlElement("FIAS_AOID")]
            public string Fias_aoid { get; set; }

            [XmlElement("FIAS_HOUSEID")]
            public string Fias_houseid { get; set; }

            [XmlElement("SUBJ")]
            public string Subj { get; set; }

            [XmlElement("INDX")]
            public string Indx { get; set; }

            [XmlElement("OKATO")]
            public string Okato { get; set; }

            [XmlElement("RNNAME")]
            public string Rnname { get; set; }

            [XmlElement("NPNAME")]
            public string Npname { get; set; }

            [XmlElement("UL")]
            public string Ul { get; set; }

            [XmlElement("DOM")]
            public string Ss { get; set; }

            [XmlElement("KORP")]
            public string Korp { get; set; }

            [XmlElement("KV")]
            public string Kv { get; set; }

        }

        public class ADDRES_G
        {
            [XmlElement("BOMG")]
            public string Bomg { get; set; }

            [XmlElement("FIAS_AOID")]
            public string Fias_aoid { get; set; }

            [XmlElement("FIAS_HOUSEID")]
            public string Fias_houseid { get; set; }

            [XmlElement("SUBJ")]
            public string Subj { get; set; }

            [XmlElement("INDX")]
            public string Indx { get; set; }

            [XmlElement("OKATO")]
            public string Okato { get; set; }

            [XmlElement("RNNAME")]
            public string Rnname { get; set; }

            [XmlElement("NPNAME")]
            public string Npname { get; set; }

            [XmlElement("UL")]
            public string Ul { get; set; }

            [XmlElement("DOM")]
            public string Ss { get; set; }

            [XmlElement("KORP")]
            public string Korp { get; set; }

            [XmlElement("KV")]
            public string Kv { get; set; }

            [XmlElement("DREG")]
            public string Dreg { get; set; }


        }

        public class OLD_PERSON
        {
            [XmlElement("FAM")]
            public string Fam { get; set; }

            [XmlElement("IM")]
            public string Im { get; set; }

            [XmlElement("OT")]
            public string Ot { get; set; }

            [XmlElement("W")]
            public string W { get; set; }

            [XmlElement("DR")]
            public string DR { get; set; }

            [XmlElement("OLD_ENP")]
            public string Old_enp { get; set; }

            [XmlElement("MR")]
            public string MR { get; set; }

        }

        public class PERSON
        {
            [XmlElement("FAM")]
            public string Fam { get; set; }

            [XmlElement("IM")]
            public string Im { get; set; }

            [XmlElement("OT")]
            public string Ot { get; set; }

            [XmlElement("W")]
            public string W { get; set; }

            [XmlElement("DR")]
            public string DR { get; set; }

            [XmlElement("MR")]
            public string MR { get; set; }

            [XmlElement("DOST")]
            public List<string> Dost { get; set; }

            [XmlElement("BIRTH_OKMS")]
            public string Birth_okms { get; set; }

            [XmlElement("C_OKSM")]
            public string C_okms { get; set; }

            [XmlElement("SS")]
            public string Ss { get; set; }

            [XmlElement("KATEG")]
            public string Kateg { get; set; }

            [XmlElement("PHONE")]
            public string Phone { get; set; }

            [XmlElement("EMAIL")]
            public string Email { get; set; }

            [XmlElement("FIOPR")]
            public string Fiopr { get; set; }

            [XmlElement("CONTACT")]
            public string Contact { get; set; }

            [XmlElement("DDEATH")]
            public string Ddeath { get; set; }
        }







       [Serializable]
        [XmlRoot("OPLIST")]
        public class OPLIST_NEW:OPLIST
        {
            [XmlElement("OP")]
            new public List<OP_NEW> Op { get; set; }
            public OPLIST_NEW():base()
            {
                Op = new List<OP_NEW>();
            }

        }

        public class OP_NEW : OP
        {
            [XmlElement("VIZIT")]
            new public VIZIT_NEW Vizit { get; set; }
            public OP_NEW() : base()
            {
                Vizit = new VIZIT_NEW();
            }

        }
        public class VIZIT_NEW : VIZIT
        {
            [XmlElement("VS_FORM")]
            public string Vsforms { get; set; }

        }




        private void button4_Click(object sender, EventArgs e)
        {
            string fileName = "D:\\Коновалов\\Пример.XML";
             OPLIST oplist = new OPLIST();

             XDocument doc = XDocument.Load(fileName);
             var xs = new XmlSerializer(typeof(OPLIST));
             oplist = (OPLIST)xs.Deserialize(doc.CreateReader());  


            OPLIST_NEW oplist_new = new OPLIST_NEW();
            XDocument doc_new = XDocument.Load(fileName);
            var xs_new = new XmlSerializer(typeof(OPLIST_NEW));
            oplist_new = (OPLIST_NEW)xs_new.Deserialize(doc_new.CreateReader());
            string s = "";

        }

Это пример того чего бы я хотел сделать, немного подправить и можно запустить

введите сюда описание изображения

А проблема вот в этом


Ответы (1 шт):

Автор решения: Vlad

Если я правильно понял, что вы хотите получить, то у вас есть два пути (буду рассматривать на примере OPLIST, для остальных различающихся типов применяются аналогичные приемы):

  1. Выделить общий абстрактный базовый тип и сделать для него наследников для конкретных операций:

    public abstract class BASE_OPLIST
    {
        [XmlAttribute("FILENAME")]
        public string Filename { get; set; }
    
        [XmlAttribute("NRECORDS")]
        public string Nrecords { get; set; }
    
        [XmlAttribute("PRZCOD")]
        public string Przcod { get; set; }
    
        [XmlAttribute("SMOCOD")]
        public string Smocod { get; set; }
    
        [XmlAttribute("VERS")]
        public string Vers { get; set; }
    }
    
    [Serializable]
    [XmlRoot("OPLIST")]
    public class OPLIST : BASE_OPLIST
    {
        [XmlElement("OP")]
        public List<OP> Op { get; set; }
    
        public OPLIST()
        {
            Op = new List<OP>();
        }
    }
    
    [Serializable]
    [XmlRoot("OPLIST")]
    public class OPLIST_NEW : BASE_OPLIST
    {
        [XmlElement("OP")]
        public List<OP_NEW> Op { get; set; }
    
        public OPLIST_NEW()
        {
            Op = new List<OP_NEW>();
        }
    }
    
  2. Использовать generics. Для этого создаем обобщенный тип и указываем его в сериализаторе/десериализаторе:

    [Serializable]
    [XmlRoot("OPLIST")]
    public class OPLIST<T>
    {
        [XmlAttribute("FILENAME")]
        public string Filename { get; set; }
    
        [XmlAttribute("NRECORDS")]
        public string Nrecords { get; set; }
    
        [XmlAttribute("PRZCOD")]
        public string Przcod { get; set; }
    
        [XmlAttribute("SMOCOD")]
        public string Smocod { get; set; }
    
        [XmlAttribute("VERS")]
        public string Vers { get; set; }
    
        [XmlElement("OP")]
        public List<T> Op { get; set; }
        public OPLIST()
        {
            Op = new List<T>();
        }
    }
    
    public void Deserialize()
    {
        XDocument doc = XDocument.Load(fileName);
        var xs = new XmlSerializer(typeof(OPLIST<Op>));
        var oplist = (OPLIST<Op>)xs.Deserialize(doc.CreateReader());
    
        XDocument doc_new = XDocument.Load(fileName);
        var xs_new = new XmlSerializer(typeof(OPLIST<Op_NEW>));
        var oplist_new = (OPLIST<Op_NEW>)xs_new.Deserialize(doc_new.CreateReader());
    }
    

Первый вариант более гибкий, но требует больше кода. Второй вариант лаконичнее, но если количество вложенных обобщений будет расти, то код станет менее читаемым. Например, typeof(OPLIST<Op<Visit_NEW>>). Я бы воспользовался первым вариантом. Либо попробовал бы их объединить, сделав базовый абстрактный тип обобщением.

→ Ссылка