开发者

inheritance in C#: create an instance initialized with values of a superclass instance

I'm pretty sure this is impossible, but here goes..

I have a custom class in C# called Person which has a few properties such as Age, Height etc.

I then make a new class called Employee which inherits from Person but I don't yet add any other 开发者_如何学编程properties to Employee. So its basically just a Person still, except its called an Employee.

Now say I have an instance of Person called SomePerson. How can I create a new Employee instance that has all of the values it inherited from Person, set to those inside SomePerson. Like casting from a Person into an Employee.. But without me having to manually specify each and every property that needs to be set..

Something like..

Employee NewEmployee = (Employee)SomePerson;

But of course you get the error saying "Can't convert a Person into an Employee" etc.

Is AutoMapper the only practical solution to do things like this if you say had 300 properties in the involved objects??

UPDATE:

Auto-Mapper doesn't seem to handle my objects..

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
}

where "Employee" is auto-generated by LINQ to SQL..


AutoMapper is a good solution in this case. If you're not going to use a property mapping framework, and you're not willing to create a copy constructor public Employee(Person person), or an implicit/explicit conversion, how else do you expect to copy the properties across. Realistically you could

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 Constructor

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

3.Implicit/Explicit Conversion

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

4.AutoMapper

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

5.Combination of 3/4:

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

A note on implicit/explicit conversion operators: I believe in using these you won't be generating CLS-compliant code.

As @Mitch Wheat has already said, if you have an object with over 300 properties, I would reconsider what that object actually represents. Refactor refactor refactor.


You can use automaper for this purpose, without any configuration.

here's an example:

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


Create a constructor on Employee that takes a Person instance. Of course you'll have to fill in all the properties (maybe Resharper can help?)


If you have relatively simple properties, reflection will probably be the quickest and easiest solution to map property values.

Contrary to popular belief, reflection really isn't that bad; Rick Strahl dispels this myth in this article: http://www.west-wind.com/weblog/posts/351.aspx.

Create the following constructor for 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);
    }
}

Now simply instantiate an Employee object like so:

Employee NewEmployee = new Employee(SomePerson);


"they are complex LINQ to SQL Model classes" -- Aaron

If you have a table that maps to one of several possible classes, you can use LINQ to SQL's Inheritance Hierarchies. It means that if you use the same table for several types of conceptual entities, you can have LINQ to SQL automatically create the appropriate class. Each class can have different properties which can be a subset of the columns in the table.

There are some limitations. You can use only one table per inheritance hierarchy and you must have a discriminator column that tells LINQ to SQL which class should be used.


When you start a new job, is a new person born who is not you, and the old you killed?

If your design is based on that scenario, as it appears, then the practice in your organisation is very strange.

Instead, a person has an employment relationship with an employer.

Don't use inheritance to model roles; allow the same person to have roles which represent their relationships with other objects.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜