2011-01-08 5 views
4

Я уверен, что это невозможно, но здесь идет ..Глупый вопрос наследования в C#

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

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

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

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

Employee NewEmployee = (Employee)SomePerson; 

Но, конечно, вы получите сообщение об ошибке говоря: «Невозможно преобразовать Лицо в Работника» и т. д.

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

UPDATE:

Авто-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 
} 

где "Сотрудник" автоматически генерируется с помощью LINQ к SQL ..

+0

Поиск нужного решения называется множественным наследованием в C#, которого не существует. – too

+0

Я бы удалил наследование «VMEmployee: Employee». Вам необходимо определить свою модель представления с подмножеством свойств из вашей модели домена Employee. –

+0

Почему я снова использую DataAnnotations? Если я вручную переучитываю каждое свойство 4 раза, это становится смешным. Один раз в каждой из двух ViewModels и один раз в каждом из двух классов проверки. Это совершенно смешно. Просто для проверки в двух разных ситуациях. Я мог бы также написать валидацию по старой школе. Должен быть более разумный способ. В противном случае DataAnnotations бесполезны. – Aaron

ответ

4

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.Implicit/Явное преобразование

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

4.AutoMapper

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

5.Combination 3/4:

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

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

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

+0

Ok AutoMapper это. Работает ли он с дочерними сложными объектами? Большое спасибо. – Aaron

+0

Да, AutoMapper поддерживает проецирование, поэтому, когда вы подключаете карту, «Mapper.CreateMap (). ForMember (e => e.ComplexProperty, o => o.MapFrom (p => new ComplexProperty (p.Name))); 'Вы должны взглянуть на примеры (http://automapper.codeplex.com/) –

+0

Попытка сопоставить MyProject.Data.Employee с MyProject.ViewModels.VMEmployee. Исключение типа 'AutoMapper.AutoMapperMappingException' было выброшено. – Aaron

0

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

+0

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

+0

@Aaron: 1. Отражение (тьфу!), 2. ReSharper (возможно), 3. Класс с 300 свойствами? Drawing Board .... –

+0

Хорошо, их не 300, но они сложны для классов LINQ to SQL Model. И они также содержат дочерние сложные классы. Например. Адрес (который сам по себе может иметь StreetName, StreetNumber и т. Д. И т. Д.) – Aaron

1

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

вот пример:

Employee employee = Mapper.Map<Person, Employee>(person); 
+0

До сих пор мне это нравится больше всего, поскольку он (а) не привлекает хардкорных хаков, таких как Reflection, (b) включает в себя одну строку кода и (c) не содержит никакой конфигурации. Мой следующий вопрос: почему не что-то подобное встраивается в .Net в некотором роде. Потребность растет, в частности, с ASP.Net MVC. – Aaron

+0

Сколько DLL-файлов у вас есть в вашей папке Bin для использования AutoMapper? Я не поклонник ненужного раздувания. – Ryan

+0

Точно моя собственная школа мысли. Как правило, чем больше дополнений, тем меньше надежность и более высокое будущее обслуживание. Я очень анти-дополнения в целом. Вы возвращаетесь через 3 года после выхода ASP.Net MVC10, и ваше решение не создается, потому что вы используете AutoMapper 1.01. Это проблема с надстройками, и я узнал об этом по опыту работы над некоторыми мамонтовыми решениями с помощью слишком большого количества надстроек. Во всяком случае, я в отчаянии и расследую AutoMapper. Автор кажется умным, его единственной DLL и очень низким раздуванием. – Aaron

-1

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

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

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

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

+0

Да, полностью согласен, но я просто составляю пример Person/Employee, чтобы сделать очень своеобразную ситуацию легкой для общения .. – Aaron

+0

@Aaron Затем используйте пример, который действительно соответствует этой проблеме, в противном случае это не настоящий вопрос. –

+0

Хорошо, Пил, вот полный вопрос. Посмотрите, что вы можете сделать: http://stackoverflow.com/questions/4636707/asp-net-mvc2-set-viewmodel-values-with-retrieved-from-db-objects-values-with-d – Aaron

0

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

Вопреки распространенному мнению, отражение действительно не так уж плохо; Рик Страйл рассеивает этот миф в этой статье: 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

Спасибо, Брилли. Мне нравится, что вы думаете о том, чтобы придерживаться собственного кода проблемы с MS, который имеет лучшую вероятность будущей жизни, но в моем случае я имею дело со сложными объектами с дочерними сложными объектами, которые автоматически генерируются LINQ to SQL. Поэтому я думаю, что именно здесь AutoMapper имеет репутацию сияющего больше. – Aaron

0

"они являются сложными LINQ к SQL классов Model" - Аарон

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

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

Смежные вопросы