наследование в C #: создать экземпляр, инициализированный значениями экземпляра суперкласса - PullRequest
4 голосов
/ 08 января 2011

Я почти уверен, что это невозможно, но здесь идет ..

У меня есть пользовательский класс в C #, называемый Person, который имеет несколько свойств, таких как Возраст, Рост и т. Д.

Затем я создаю новый класс Employee, который наследуется от Person, но я пока не добавляю никаких других свойств в Employee.Так что в основном это все еще Person, за исключением того, что он называется Employee.

Теперь скажите, что у меня есть экземпляр Person, называемый SomePerson.Как я могу создать новый экземпляр Employee, который имеет все значения, которые он унаследовал от Person, и установить их в SomePerson.Как приведение человека к сотруднику. Но мне не нужно вручную указывать каждое свойство, которое нужно установить ..

Что-то вроде ..

Employee NewEmployee = (Employee)SomePerson;

Но, конечно,появляется сообщение «Не удается преобразовать человека в сотрудника» и т. д.

Является ли AutoMapper единственным практическим решением, позволяющим делать подобные вещи, если вы говорите, что в задействованных объектах имеется 300 свойств ??

ОБНОВЛЕНИЕ:

Кажется, Auto-Mapper не обрабатывает мои объекты ..

Employee SomeEmployee = EmployeeRepository.GetEmployee(SomeEmployeeID);

// Populate the ViewModel with the Person fetched from the db, ready for editing..
VMEmployee EmployeeToEdit = Mapper.Map<Employee, VMEmployee>(SomeEmployee);


// ViewModel based on Employee with Validation applied..
[MetadataType(typeof(Employee_Validation))]
public class VMEmployee : Employee
{
    // Absolutely nothing here
}

, где "Employee" автоматически генерируется LINQ дляSQL ..

Ответы [ 6 ]

4 голосов
/ 08 января 2011

AutoMapper является хорошим решением в этом случае.Если вы не собираетесь использовать инфраструктуру сопоставления свойств и не хотите создавать конструктор копирования public Employee(Person person) или неявное / явное преобразование, как еще вы собираетесь копировать свойства.Реально вы могли бы

1.Reflection

public void Map<TSource, TDestination>(TSource source, TDestination destination)
{
  var props = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
  var type = typeof(TDestination);

  foreach (var prop in props)
  {
    object value = prop.GetValue(source, null);

    var prop2 = type.GetProperty(prop.Name);
    if (prop2 == null)
      continue;

    if (prop.PropertyType != prop2.PropertyType)
      continue;

    prop2.SetValue(destination, value, null);
  }
}

2.Копировальный конструктор

public Employee(Person person)
{
  // Copy properties
}

3. Явное / явное преобразование

public static implicit operator Employee(Person person)
{
  // Build instance and return
}

4.AutoMapper

Mapper.Map<Person, Employee>(person);

5. Комбинация 3/4:

public static implicit operator Employee(Person person)
{
  return Mapper.Map<Person, Employee>(person);
}

Примечание по операторам неявного / явного преобразования: я считаю, что при их использовании вы не будете генерировать CLS-совместимый код.

Как уже сказал @Mitch Wheat, если у вас есть объект с более чем 300 свойствами, я бы пересмотрел то, что этот объект на самом деле представляет.Рефакторинг Реактор Реактор.

1 голос
/ 08 января 2011

Вы можете использовать automaper для этой цели, без какой-либо конфигурации.

вот пример:

Employee employee = Mapper.Map<Person, Employee>(person);
0 голосов
/ 08 января 2011

«это сложные классы LINQ to SQL Model» - Аарон

Если у вас есть таблица, которая отображается на один из нескольких возможных классов, вы можете использовать LINQ to SQL Inheritance Hierarchies . Это означает, что если вы используете одну и ту же таблицу для нескольких типов концептуальных сущностей, LINQ to SQL может автоматически создавать соответствующий класс. Каждый класс может иметь разные свойства, которые могут быть подмножеством столбцов в таблице.

Есть некоторые ограничения. Вы можете использовать только одну таблицу на иерархию наследования, и у вас должен быть столбец дискриминатора, который сообщает LINQ to SQL, какой класс следует использовать.

0 голосов
/ 08 января 2011

Если у вас относительно простые свойства, отражение, вероятно, будет самым быстрым и простым решением для сопоставления значений свойств.

Вопреки распространенному мнению, отражение действительно не так уж и плохо;Рик Страл развеивает этот миф в этой статье: http://www.west -wind.com / weblog / posts / 351.aspx .

Создайте следующий конструктор для Employee:

public Employee(Person person)
{
    // clone property values
    foreach (var property in person.GetType().GetProperties().Where(property => property.CanRead && property.CanWrite))
    {
        property.SetValue(this, property.GetValue(user, null), null);
    }
}

Теперь просто создайте экземпляр объекта Employee следующим образом:

Employee NewEmployee = new Employee(SomePerson);
0 голосов
/ 08 января 2011

Когда вы начинаете новую работу, рождается ли новый человек, который не вы, и тот, кого вы убили?

Если ваш дизайн основан на том сценарии, как он выглядит, то практика в вашей организации очень странная.

Вместо этого человек имеет трудовые отношения с работодателем.

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

0 голосов
/ 08 января 2011

Создайте конструктор на Employee, который принимает экземпляр Person.Конечно, вам нужно будет заполнить все свойства (может быть, Resharper может помочь?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...