Наследование С#. Производный класс из базового класса

У меня есть базовый класс

public class A   
{
    public string s1;
    public string s2;
}

У меня также есть производный класс:

public class B : A
{
    public string s3;
}

Предположим, что моя программа создала экземпляр класса A.

A aClassInstance = new A();

были установлены некоторые параметры:

aClassInstance.s1 = "string 1";
aClassInstance.s2 = "string 2";

В этот момент я хотел бы создать экземпляр класса B. Но я бы хотел, чтобы B уже имел значения моего экземпляра класса A.

Этот DID НЕ работает:

public B bClassInstance = new B():
bClassInstance = (B)aClassInstance;

НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ:

Создал метод клонирования в классе A.

public B cloneA() {    
    A a = new A();
    a = (A)this.MemberwiseClone()
    return(B)a;
}

Код VS принимает оба значения выше, но я получаю ошибки во время выполнения

Пожалуйста, помогите

Ответы

Ответ 1

Основная проблема, с которой вы столкнулись, заключается в том, что вам нужно построить экземпляр типа B (который содержит причины типа A). Ваш подход к клонированию экземпляра A не будет работать, потому что это дает вам экземпляр типа A, который вы не можете преобразовать в B.

Я бы написал конструкторы для классов A и B, которые берут параметр типа A. Конструктор класса B просто передает значение его базовому классу A. Конструктор класса A знает, как скопировать поля в себя:

class A {
    public A(A copyMe) {
        s1 = copyMe.s1;
        ...
    }

class B : A {

    public B(A aInstance) : base(aInstance) {
    }

}

Используйте его следующим образом:

A a = new A();
a.s1 = "...";

B b = new B(a);

ИЗМЕНИТЬ

Если вы не хотите менять конструктор A при добавлении новых полей или реквизитов, вы можете использовать отражение для копирования свойств. Либо используйте специальный атрибут, чтобы украсить то, что вы хотите скопировать, или скопируйте только все реквизиты/поля A:

public A (A copyMe) {
    Type t = copyMe.GetType();
    foreach (FieldInfo fieldInf in t.GetFields())
    {
        fieldInf.SetValue(this, fieldInf.GetValue(copyMe));
    }
    foreach (PropertyInfo propInf in t.GetProperties())
    {
        propInf.SetValue(this, propInf.GetValue(copyMe));
    }
}

Я не пробовал код, но точка должна стать ясной.

Ответ 2

Вы можете создать общий метод клонирования в классе A:

     public T Clone<T>() where T : A, new() {
          return new T() { a = this.a, b = this.b};
     }

Или, если вы хотите сделать клонирование расширяемым:

     public T Clone<T>() where T : A, new() {
          var result = new T();
          this.CopyTo(result);
          return result;
     }

     protected virtual void CopyTo(A other) {
          other.a = this.a;
          other.b = this.b;
     }

Вы используете его следующим образом:

     A  a = new A();
     // do stuff with a
     // Create a B based on A:
     B b = a.Clone<B>();

Обратите внимание: в вашем примере как новый A(), так и MemberwiseClone создадут новый объект типа A.

Если вы не хотите самостоятельно кодировать метод копирования, вы можете посмотреть на инструмент, например AutoMapper.

Ответ 3

После игры и чтения всего, на что я мог смотреть, оба вышеупомянутых решения GvS и Jan работают. Однако конечный результат, который я хотел достичь, не должен быть вынужден выписывать каждого члена в методах копирования.

Почему: a) Если класс отредактирован и добавлен другой объект, метод копирования должен быть обновлен. Если кто-то еще обновляет класс, они могут забыть это сделать.

b) Могут быть много членов, и их назначение может занять много времени.

c) Он просто не "чувствует" себя правильно. (Наверное, потому что я очень ленив).

К счастью, я не единственный с теми же мыслями. С помощью ValueInjector найдено очень простое решение. (о них много говорили на этих досках).

После получения dll (http://valueinjecter.codeplex.com/documentation)

Код будет выглядеть следующим образом:

A a = new A();
a.s1 = "...";


B b = new B();
b.InjectFrom(a);

Что это:)

Очевидно, вам нужно включить:

using Omu.ValueInjecter;

И не забудьте добавить его в ссылки.