Наследование С#. Производный класс из базового класса
У меня есть базовый класс
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;
И не забудьте добавить его в ссылки.