Click here to Skip to main content
15,883,809 members
Articles / Programming Languages / C# 4.0

Constructing an instance class from its base class instance

Rate me:
Please Sign up or sign in to vote.
4.89/5 (11 votes)
8 Sep 2009CPOL2 min read 42.6K   18   7
A Generic way to construct an instance of a class from an instance of its base class.

Introduction

This is a simple solution for a simple problem. There will not be any code attachments for this reason. Copy and paste and you're good to go :) On the same note, I will try not just copy and paste code here and hit the big green button. So bare with me just a tiny bit.

Basically...

.NET allows you to cast from an instance of a class of type T to its base class F with ease.

Example

Given the classes Male: Person: Animal:

C#
class Animal 
{
    private int _age;
    public int Age
    {
        get { return this._age; }
        set { this._age = value; }
    }

}

class Person: Animal
{
    private string _codeProjectName;
    public string CodeProjectName
    {
        get { return this._codeProjectName; }
        set { this._codeProjectName = value; }
    }

}

class Male: Person
{
    private long _ego;
    public long Ego
    {
        get { return this._ego; }
        set { this._ego = value; }
    }
}

We can simply cast a Male object to a Person or Animal, like so:

C#
...
 Person yang = new Person();
 Animal AlsoYang = (Animal)yang; // note: same memory address different pointer
...

Problem...

Time to time again, I've always had to deal with the problem of wanting to create an instance of a class of type T derived from an instance of its base class type F. (I am implying that I want to copy the Data Model, specifically properties.) Usually, I will simply create a custom constructor or write some hard-coded logic to implement this functionality.

So to do this, we will use Generics, and Reflection.

Like so...

C#
/// <summary>
/// construct a derived class of from a base class
/// </summary>
/// <typeparam name="F">type of base class</typeparam>
/// <typeparam name="T">type of class you want</typeparam>
/// <param name="Base">the instance of the base class</param>
/// <returns></returns>
public static T Construct<F, T>(F Base) where T : F, new()
{
    // create derived instance
    T derived = new T();
    // get all base class properties
    PropertyInfo[] properties = typeof(F).GetProperties();
    foreach (PropertyInfo bp in properties)
    {
        // get derived matching property
        PropertyInfo dp = typeof(T).GetProperty(bp.Name, bp.PropertyType);

        // this property must not be index property
        if (
            (dp != null)
            && (dp.GetSetMethod() != null)
            && (bp.GetIndexParameters().Length == 0)
            && (dp.GetIndexParameters().Length == 0)
        )
            dp.SetValue(derived, dp.GetValue(Base,null), null);
    }

    return derived;
}

Notice that the generic type clause states that T: F, which means that T must be a subclass of F and contains all of the public and private properties of F. (Again, this implementation deals with properties. If you want variables, be my guest.)

Note: In the above code, we are not cloning the property values, so changing the value of the derived instance will change the base instance since they are from the same pointer.

Using the darn thing...

Using the above example, we can get a new instance of a derived class of Animal such as a Person.

C#
...
Animal yang_ox = new Animal();
yang_ox.Age = 10;
Person yang = Construct<Animal, Person>(yang_ox);
// note: this is a new instance with shallow property values
 
// guess what yang.Age is?? yup its 10. Easy
...

Further thinking...

Using this approach, one can also address a similar solution for Cloning<T>(), and even Construct<F,T> where F:T.

One could also go even further with this and do some assembly injection compiled code at run time to save all this Reflection jazz.

Hope you enjoyed the short read. Hopefully I won't get any 1s. Fingers are crossed. ^_^

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Canada Canada
Engineer, maker, food lover

Comments and Discussions

 
QuestionAwesome example! Pin
Ignus Fast5-Apr-18 14:12
Ignus Fast5-Apr-18 14:12 
PraiseVery good! Pin
OriginalGriff23-Dec-17 1:47
mveOriginalGriff23-Dec-17 1:47 
QuestionIn VB ? Pin
Bib3477015-Sep-09 10:31
Bib3477015-Sep-09 10:31 
AnswerRe: In VB ? Pin
Yang Yu16-Sep-09 7:11
Yang Yu16-Sep-09 7:11 
GeneralRe: In VB ? Pin
Bib3477016-Sep-09 11:30
Bib3477016-Sep-09 11:30 
GeneralRe: In VB ? Pin
Member 1306534628-Feb-18 23:04
Member 1306534628-Feb-18 23:04 
GeneralRedundant Cast Pin
Richard Deeming15-Sep-09 2:30
mveRichard Deeming15-Sep-09 2:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.