Создать экземпляр производного класса из экземпляра базового класса
От: Pek2014 Россия  
Дата: 11.04.17 07:59
Оценка:
Довольно часто мне приходится создавать экземпляр производного класса, имея в
качестве прототипа экземпляр базового класса. При это приходится заниматься
ручным копированием всего состояния (всех свойств) объекта источника
в целевой объект.

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


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: Создать экземпляр производного класса из экземпляра базового класса
От: hardcase Пират http://nemerle.org
Дата: 11.04.17 08:23
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Неужели средства языка (или ещё какие-нибудь ухищрения) не позволяют избежать

P>этой муторной процедуры, особенно принимая во внимание, что копирование
P>происходит из базового класса в производный?

Агрегирование. Необходимые свойства выносятся в отдельный класс и его экземпляр передается куда необходимо.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Создать экземпляр производного класса из экземпляра базового класса
От: Pek2014 Россия  
Дата: 11.04.17 08:32
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Агрегирование. Необходимые свойства выносятся в отдельный класс и его экземпляр передается куда необходимо.


Да. Это решило бы проблемы. Но ...

"По техническим причинам" не получается этого делать.
"По независимым от меня причинам" я вынужден применять наследование. ... это нужно для совместимости с чужим кодом.

Короче, для меня наследование это данность...
Неужели я обречён писать километры монотонного, тупого кода? И потом поддерживать его в актуальном состоянии?
Re: Создать экземпляр производного класса из экземпляра базового класса
От: Qulac Россия  
Дата: 11.04.17 08:51
Оценка:
Здравствуйте, 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]: Создать экземпляр производного класса из экземпляра базового класса
От: Pek2014 Россия  
Дата: 11.04.17 09:11
Оценка:
Здравствуйте, 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]: Создать экземпляр производного класса из экземпляра базового класса
От: seregaa Ниоткуда http://blogtani.ru
Дата: 11.04.17 09:24
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Итого, получаем писанины :

P>- три новых конструктора (два для наследника и один для базы)
P>- конструктор базового класса громоздкий, тупой, в ручную написанный....

P>Конечно, я знаю про аутомапперы.

P>Они могут помочь писать конструктор копирования базового класса.
P>Но неужели без аутомапперов не обойтись? Задачка выглядит так просто....

Как вариант: объявить классы partial и нагенерировать с помощью t4 и рефлексии конструкторы в отдельном файле.
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re[4]: Создать экземпляр производного класса из экземпляра базового класса
От: Pek2014 Россия  
Дата: 11.04.17 09:31
Оценка:
Здравствуйте, seregaa, Вы писали:

S>Здравствуйте, Pek2014, Вы писали:


P>>Конечно, я знаю про аутомапперы.

P>>Они могут помочь писать конструктор копирования базового класса.
P>>Но неужели без аутомапперов не обойтись? Задачка выглядит так просто....

S>Как вариант: объявить классы partial и нагенерировать с помощью t4 и рефлексии конструкторы в отдельном файле.


А компилятор, ничем не может помочь?
Ведь дело тривиальное: надо обеспечить поверхностное копирование всех полей.

Если не ошибаюсь, то компилятор C++ это умел. А C# разучился?!
Re: Создать экземпляр производного класса из экземпляра базового класса
От: Max Mustermann  
Дата: 11.04.17 09:59
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Неужели средства языка (или ещё какие-нибудь ухищрения) не позволяют избежать этой муторной процедуры


Позволяют, например рефлексией. Или рукопсный велосипед(там делов на пол часа), или стороннее что-то типа AutoMapper.
Re[3]: Создать экземпляр производного класса из экземпляра базового класса
От: hardcase Пират http://nemerle.org
Дата: 11.04.17 11:34
Оценка: 2 (1)
Здравствуйте, 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: Создать экземпляр производного класса из экземпляра базового класса
От: vorona  
Дата: 11.04.17 11:42
Оценка: +1
Здравствуйте, Pek2014, Вы писали:

AutoMapper
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.