Довольно часто мне приходится создавать экземпляр производного класса, имея в
качестве прототипа экземпляр базового класса. При это приходится заниматься
ручным копированием всего состояния (всех свойств) объекта источника
в целевой объект.
Неужели средства языка (или ещё какие-нибудь ухищрения) не позволяют избежать
этой муторной процедуры, особенно принимая во внимание, что копирование
происходит из базового класса в производный?
public class B
{
public int N {get; set;}
...
public string S {get; set;}
}
public class D : B
{
public double D {get; set;}
}
var b = new B { N = 5, ... S = "A"}
var d = new D
{
N = b.N, // Можно вот это не писать?
...
S = b.S // Можно вот это не писать?
D = 1.5
};
Re: Создать экземпляр производного класса из экземпляра базового класса
Здравствуйте, Pek2014, Вы писали:
P>Неужели средства языка (или ещё какие-нибудь ухищрения) не позволяют избежать P>этой муторной процедуры, особенно принимая во внимание, что копирование P>происходит из базового класса в производный?
Агрегирование. Необходимые свойства выносятся в отдельный класс и его экземпляр передается куда необходимо.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Создать экземпляр производного класса из экземпляра базового класса
Здравствуйте, hardcase, Вы писали:
H>Агрегирование. Необходимые свойства выносятся в отдельный класс и его экземпляр передается куда необходимо.
Да. Это решило бы проблемы. Но ...
"По техническим причинам" не получается этого делать.
"По независимым от меня причинам" я вынужден применять наследование. ... это нужно для совместимости с чужим кодом.
Короче, для меня наследование это данность...
Неужели я обречён писать километры монотонного, тупого кода? И потом поддерживать его в актуальном состоянии?
Re: Создать экземпляр производного класса из экземпляра базового класса
Здравствуйте, Pek2014, Вы писали:
P>Довольно часто мне приходится создавать экземпляр производного класса, имея в P>качестве прототипа экземпляр базового класса. При это приходится заниматься P>ручным копированием всего состояния (всех свойств) объекта источника P>в целевой объект.
P>Неужели средства языка (или ещё какие-нибудь ухищрения) не позволяют избежать P>этой муторной процедуры, особенно принимая во внимание, что копирование P>происходит из базового класса в производный?
P>
P>public class B
P>{
P> public int N {get; set;}
P> ...
P> public string S {get; set;}
P>}
P>public class D : B
P>{
P> public double D {get; set;}
P>}
P>var b = new B { N = 5, ... S = "A"}
P>var d = new D
P>{
P>N = b.N, // Можно вот это не писать?
P>...
P>S = b.S // Можно вот это не писать?
P>D = 1.5
P>};
P>
Определите конструкторы:
public class B
{
public B(B b)
{
// тут копирование свойств
}
public int N {get; set;}
...
public string S {get; set;}
}
public class D : B
{
public D(B b):base(b)
{
}
public double D {get; set;}
}
Так наверно лучше будет.
Программа – это мысли спрессованные в код
Re[2]: Создать экземпляр производного класса из экземпляра базового класса
Здравствуйте, Qulac, Вы писали:
Q>Определите конструкторы: Q>
Q>public class B
Q>{
Q> public B(B b)
Q> {
Q> // тут копирование свойств
Q> }
Q> public int N {get; set;}
Q> ...
Q> public string S {get; set;}
Q>}
Q> public class D : B
Q> {
Q> public D(B b):base(b)
Q> {
Q> }
Q> public double D {get; set;}
Q> }
Q>
Q>Так наверно лучше будет.
Да. Так немного лучше, но...
1. Копирование свойств (это могут быть десятки свойств) всё равно делается в ручную (это тупое упражнение на внимательность ).
2. Классу-наследнику придётся ещё приделать конструктор без параметров (в моём случае он нужен "по техническим причинам").
Итого, получаем писанины :
— три новых конструктора (два для наследника и один для базы)
— конструктор базового класса громоздкий, тупой, в ручную написанный....
Конечно, я знаю про аутомапперы.
Они могут помочь писать конструктор копирования базового класса.
Но неужели без аутомапперов не обойтись? Задачка выглядит так просто....
Re[3]: Создать экземпляр производного класса из экземпляра базового класса
Здравствуйте, Pek2014, Вы писали:
P>Итого, получаем писанины : P>- три новых конструктора (два для наследника и один для базы) P>- конструктор базового класса громоздкий, тупой, в ручную написанный....
P>Конечно, я знаю про аутомапперы. P>Они могут помочь писать конструктор копирования базового класса. P>Но неужели без аутомапперов не обойтись? Задачка выглядит так просто....
Как вариант: объявить классы partial и нагенерировать с помощью t4 и рефлексии конструкторы в отдельном файле.
Здравствуйте, seregaa, Вы писали:
S>Здравствуйте, Pek2014, Вы писали:
P>>Конечно, я знаю про аутомапперы. P>>Они могут помочь писать конструктор копирования базового класса. P>>Но неужели без аутомапперов не обойтись? Задачка выглядит так просто....
S>Как вариант: объявить классы partial и нагенерировать с помощью t4 и рефлексии конструкторы в отдельном файле.
А компилятор, ничем не может помочь?
Ведь дело тривиальное: надо обеспечить поверхностное копирование всех полей.
Если не ошибаюсь, то компилятор C++ это умел. А C# разучился?!
Re: Создать экземпляр производного класса из экземпляра базового класса
Здравствуйте, Pek2014, Вы писали:
P>Короче, для меня наследование это данность... P>Неужели я обречён писать километры монотонного, тупого кода? И потом поддерживать его в актуальном состоянии?
Немного рефлексии, и рантаймовой кодогенерации, раз уж макросов в C# не видно:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
class A
{
public string X { get; set; }
public int Y { get; set; }
}
class B : A
{
public B(A prototype)
{
Mapper.Map(prototype, this);
}
}
class Program
{
static void Main(string[] args)
{
var a = new A() { X = "hello", Y = 42 };
var b = new B(a);
Console.WriteLine($"X = {b.X}, Y = {b.Y}");
}
}
static class Mapper
{
private static class Container<T>
{
public static readonly Action<T, T> Map;
static Container()
{
var sourceParam = Expression.Parameter(typeof(T));
var destinationParam = Expression.Parameter(typeof(T));
var assignments = new List<Expression>();
foreach (var property in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (property.CanRead && property.CanWrite)
{
assignments.Add(Expression.Assign(Expression.Property(destinationParam, property), Expression.Property(sourceParam, property)));
}
}
Map = (Action<T, T>)Expression.Lambda(typeof(Action<T, T>), Expression.Block(assignments), sourceParam, destinationParam)
.Compile();
}
}
public static void Map<T>(T source, T destination)
{
Container<T>.Map(source, destination);
}
}
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Создать экземпляр производного класса из экземпляра базового класса