C#中的继承:创建一个用超类实例的值初始化的实例

时间:2011-01-08 10:27:39

标签: c# inheritance

我很确定这是不可能的,但是这里......

我在C#中有一个名为Person的自定义类,它有一些属性,如Age,Height等。

然后我创建了一个名为Employee的新类,它继承自Person但我还没有向Employee添加任何其他属性。所以它基本上只是一个人,除了它被称为员工。

现在说我有一个名为SomePerson的Person实例。如何创建一个新的Employee实例,该实例具有从Person继承的所有值,设置为SomePerson中的值。就像从一个Person转变为一个Employee ..但是我不必手动指定需要设置的每个属性..

像...这样的东西。

Employee NewEmployee = (Employee)SomePerson;

但是当然你得到的错误是“无法将人员转换成员工”等等。

如果你说在涉及的对象中有300个属性,AutoMapper是唯一可以做这样的事情的实用解决方案吗?

更新

自动映射器似乎无法处理我的对象..

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 to SQL自动生成..

6 个答案:

答案 0 :(得分: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.Copy构造函数

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 :(得分:1)

您可以将automaper用于此目的,无需任何配置。

这是一个例子:

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

答案 2 :(得分:0)

Employee上创建一个带有Person实例的构造函数。当然你必须填写所有属性(也许Resharper可以帮忙?)

答案 3 :(得分:0)

如果你有相对简单的属性,反射可能是映射属性值的最快最简单的解决方案。

与流行的看法相反,反思确实不是那么糟糕; Rick Strahl在这篇文章中消除了这个神话: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);

答案 4 :(得分:0)

“它们是复杂的LINQ to SQL模型类” - Aaron

如果您有一个映射到几个可能类之一的表,则可以使用LINQ to SQL's Inheritance Hierarchies。这意味着如果对多种类型的概念实体使用相同的表,则可以让LINQ to SQL自动创建相应的类。每个类可以具有不同的属性,这些属性可以是表中列的子集。

有一些限制。每个继承层次结构只能使用一个表,并且必须有一个鉴别器列,告诉LINQ to SQL应该使用哪个类。

答案 5 :(得分:-2)

当你开始一份新工作时,出生的新人是不是你,而你的老人是谁?

如果您的设计基于该场景,那么您的组织中的实践就非常奇怪了。

相反,一个人与雇主有雇佣关系。

不要使用继承来建模角色;允许同一个人拥有代表他们与其他对象的关系的角色。