none
Как из экземпляра базового типа перенести все значения в производный? RRS feed

  • Вопрос

  • Здравствуйте.
    Понадобилось сделать что-то типа обратного приведения.

    Вот пример:
    class testbase
    {
     public int variable1;
    }

    class testChild: testbase
    {
     public string variable2;

    public testChild(testbase elembase)
    {
      // как-то все поля из базового класса перекинуть сюда
      variable2 = "test";
    }

    }

    Можно конечно вручную перечислить всё, чего нужно,
    но это не очень интересно.
    Для простоты предположим, что все поля обоих классов открытые (public)., без перегрузок свойств.
    Но в принципе не исключено появление перегрузок этих.

    У меня пока 2 идеи:
    1) как-то переделать, чтобы подобное просто не понадобилось (но будет туго, много воды утекло).
    2) что-то про рефлексию придумать, не знаю что., может по именам поискать.

    Есть у кого-то решение?


    • Изменено INFEL8 20 марта 2013 г. 10:25 букву пропустил
    20 марта 2013 г. 10:24

Ответы

  • Понял, вам нужно значения из другого объекта перекинуть в этот. Тогда лучше оставьте всё как есть, это лучший способ. Можно автоматизировать этот процесс рефлексией, пройдясь по всем полям и скопировав их, но это займёт много ресурсов. Если это не критично, вот код на скорую руку, но не рекомендую.

    namespace Test
    {
      class Program
      {
        static void Main(string[] args)
        {
          A a = new A(25,30);
          B b = new B();
          Console.WriteLine(b.ToString());
          b.Copy(a);
          Console.WriteLine(b.ToString());
        }
      }
      public class A
      {
        private int value1;
        private int value2;
        public A(int value1 = 0, int value2 = 0)
        {
          this.value1 = value1;
          this.value2 = value2;
        }
        public A Clone()
        {
          return (A)this.MemberwiseClone();
        }
        public override string ToString()
        {
          return value1.ToString() + " " + value2.ToString();
        }
      }
      public class B: A
      {
        private int Value2;
        public override string ToString()
        {
          return base.ToString();
        }
      }
      static class Extension
      {
        public static void Copy(this B b, A a)
        {
          var bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
          foreach (FieldInfo fis in a.GetType().GetFields(bf))
            fis.SetValue(b, fis.GetValue(a));
        }
      }
    }

    • Предложено в качестве ответа Abolmasov Dmitry 20 марта 2013 г. 17:52
    • Помечено в качестве ответа INFEL8 21 марта 2013 г. 4:42
    20 марта 2013 г. 13:23
    Модератор

Все ответы

  • А зачем их переуидывать, они и так будут, достаточно объявить их максим как protected.
    20 марта 2013 г. 11:27
    Модератор
  • да вот что-то не выходит.
    сами то поля понятно, что там появятся,
    А вот значения пока приходится вручную перекидывать или так в конструкторе или через перегрузку приведения типа.
    20 марта 2013 г. 11:40
  • Значения должны указывать вы, а вот есть более короткий способ: base - ключекое слово, для доступа к содержимому базового класса.

    "через перегрузку приведения типа." - а это что значит, что за новая терминология?

    20 марта 2013 г. 12:08
    Модератор
  • Я думаю принципы ООП в C# не сильно отличаются от VB'шных, поэтому тоже поучаствую.

    Как я понял вы хотите в классе Б, наследнике класса А получить значения от экземпляра класса А. Если я понял правильно, то "родного" способа нет, так как при создании класса Б вы наследуете его не от экземпляра класса, а от базового класса, который содержит только начальные значения.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    20 марта 2013 г. 12:34
    Отвечающий
  • Понял, вам нужно значения из другого объекта перекинуть в этот. Тогда лучше оставьте всё как есть, это лучший способ. Можно автоматизировать этот процесс рефлексией, пройдясь по всем полям и скопировав их, но это займёт много ресурсов. Если это не критично, вот код на скорую руку, но не рекомендую.

    namespace Test
    {
      class Program
      {
        static void Main(string[] args)
        {
          A a = new A(25,30);
          B b = new B();
          Console.WriteLine(b.ToString());
          b.Copy(a);
          Console.WriteLine(b.ToString());
        }
      }
      public class A
      {
        private int value1;
        private int value2;
        public A(int value1 = 0, int value2 = 0)
        {
          this.value1 = value1;
          this.value2 = value2;
        }
        public A Clone()
        {
          return (A)this.MemberwiseClone();
        }
        public override string ToString()
        {
          return value1.ToString() + " " + value2.ToString();
        }
      }
      public class B: A
      {
        private int Value2;
        public override string ToString()
        {
          return base.ToString();
        }
      }
      static class Extension
      {
        public static void Copy(this B b, A a)
        {
          var bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
          foreach (FieldInfo fis in a.GetType().GetFields(bf))
            fis.SetValue(b, fis.GetValue(a));
        }
      }
    }

    • Предложено в качестве ответа Abolmasov Dmitry 20 марта 2013 г. 17:52
    • Помечено в качестве ответа INFEL8 21 марта 2013 г. 4:42
    20 марта 2013 г. 13:23
    Модератор
  • я тут подумал ещё чуток,
    и придумал, что можно же использовать unsafe структуры.
    Жаль только, что потом глянул, а там не так то и легко переделать на это..

    Думаю, буду пользоваться вашим вариантом, операции разовые в основном.

    Ну и ещё можно такой вариант:
    сделать методы возвращающие массив байт,
    и из байт заполняющие поля.
    А далее как с unsafe структурами можно, или как-нибудь.
    Но это делать надо.

    21 марта 2013 г. 4:42