Josh
Josh

Reputation: 8477

Transform class to a derived class

Is there a way to transform a base class into its derived class?

Here is a simple example of two classes:

namespace BLL
{
    public class Contact 
    {
       public int ContactID { get; set; }
       public string Name { get; set; }

       public Contact(){}
    }
}

namespace BLL
{
    public class SpecialContact : Contact
    {
       public SpecialContact(){}
    }
}

Ideally, I could do something like this:

Contact contact = new Contact();
SpecialContact specialContact = new SpecialContact();

contact.ContactID = 123;
contact.Name = "Jeff";

specialContact = contact;

This code of course throws an error. Apart from writing another constructor for SpecialContact or method that sets each property, is there any other solution?

Upvotes: 3

Views: 591

Answers (5)

Henk Holterman
Henk Holterman

Reputation: 273784

Outside of writing another constructor for SpecialContact or method that sets each property, is there another solution?

No, not really.
You can automate it with Reflection, but that's about it.

But do note that with a proper design this should almost never be called for. It is not a normal use of (derived) classes.

If Contracts can change into SpecialContracts over time then you either create a new object or model it with a ContactType property and maybe some composition.

Upvotes: 2

BrokenGlass
BrokenGlass

Reputation: 161002

If you are just interested in copying properties from one class instance to another (regardless of the relationship of these classes) you can use a mapping tool like AutoMapper.

Your specific example would look like this:

Mapper.CreateMap<Contact, SpecialContact>();
Contact contact = new Contact();
contact.ContactID = 123;
contact.Name = "Jeff";
SpecialContact specialContact = Mapper.Map<Contact, SpecialContact>(contact);

Upvotes: 3

Krizz
Krizz

Reputation: 11552

It is illegal to assign Base class reference to the Derived class reference variable.

Variable of type X can only be a reference to an object of type X or derived.

You probably need to have another instance of SpecialContact which contains the same data as existing object. There is no way to avoid manual copying.

I use the following extension method when I need to copy the matching properties from one object to another incompatible one(1):

public static void AssignFrom(this object destination, object source) {
  Type dest_type = destination.GetType();
  Type source_type = source.GetType();

  var matching_props = from d in dest_type.GetProperties()
                        join s in source_type.GetProperties()
                        on d.Name equals s.Name
                        where d.IsWritable() && s.IsReadable()
                        select new {
                          source = s,
                          destination = d
                        };

  foreach (var prop in matching_props) {
    prop.destination.SetValue(destination, prop.source.GetValue(source, null), null);
  }
}

Then you can do:

specialContact.assignFrom(contact);

Please consider this a workaround. The proper solution would be to design properly your class hierarchy where you do not come to this problem.


1 Note: it matches the properties by name and assumes they are of the same type.

Upvotes: 3

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727047

Apart from re-considering your inheritance hierarchy that forces you to do this somewhat un-orthodox operation, you have several solutions, all requiring some coding.

  • You can add an explicit conversion operator to your base class
  • You can add an extension method that does the copying for you

As far as transforming your inheritance hierarchy goes, you could use the Decorator Design Pattern to add special functionality to your Contact class, giving it functionality of a SpecialContact without subclassing.

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1039438

This code of course throws an error. Outside of writing another constructor for SpecialContact or method that sets each property, is there another solution?

No, there's no other way. Reflection might help you if you want to avoid doing all the manual copying.

Upvotes: 1

Related Questions