Tag Archives: GetProperties

Casting a C# Object From its Parent

Have you ever tried to do something akin to the following:

[Fact]
public void ConvertClassToSubClass_Converts()
{
    // Arrange
    var parentClass = new SimpleTestClass();
    parentClass.Property1 = "test";
 
    // Act
    var childClass = parentClass as SimpleTestSubClass;
 
    // Assert
    Assert.Equal("test", childClass.Property1);
}

This is a simple Xunit (failing) test. The reason is fails is because you (or I) am trying to cast a general type to a specific, and C# is complaining that this may not be possible; consequently, you will get null (or for a hard cast, you’ll get an InvalidCastException.

Okay, that makes sense. After all, parentClass could actually be a SimpleTestSubClass2 and, as a result, C# is being safe because there’s (presumably – I don’t work for MS) too many possibilities for edge cases.

This is, however, a solvable problem; there are a few ways to do it, but you can simply use reflection:

public TNewClass CastAsClass<TNewClass>() where TNewClass : class
{
 
    var newObject = Activator.CreateInstance<TNewClass>();
    var newProps = typeof(TNewClass).GetProperties();
 
    foreach (var prop in newProps)
    {
        if (!prop.CanWrite) continue;
 
        var existingPropertyInfo = typeof(TExistingClass).GetProperty(prop.Name);
        if (existingPropertyInfo == null || !existingPropertyInfo.CanRead) continue;
        var value = existingPropertyInfo.GetValue(_existingClass);
        
        prop.SetValue(newObject, value, null);
    }
 
    return newObject;
}

This code will effectively transfer any class over to any other class.

If you’d rather use an existing library, you can always use this one. It’s also Open Source on Git Hib.

Dynamically copy a class from one instance to another using reflection

Occasionally, you find that you want to copy a class to another instance of itself. There are various reason, but typically the code can result in a `CopyTo()` function, with a long list of properties to be copied across. There’s nothing wrong with that and, performance-wise, it’s probably faster than what I’m suggesting in this post.

Here’s a generic method that will copy the class for you:

        private static void CopyClass<T>(T copyFrom, T copyTo)
        {
            if (copyFrom == null || copyTo == null)
                throw new Exception("Must not specify null parameters");

            var properties = copyFrom.GetType().GetProperties();

            foreach (var p in properties.Where(prop => prop.CanRead && prop.CanWrite))
            {
                object copyValue = p.GetValue(copyFrom);
                p.SetValue(copyTo, copyValue);
            }
        }

Nothing too onerous if you’ve ever seen reflection, but let’s quickly run through it. The first thing it does is ensure that both to destination and source are provided, then it gets a list of properties that can be read and written to, and copies the value across.

Obviously, this won’t include any private properties.

Here’s some test / example code for it. First, the class to copy:

    class TestClass
    {
        public string teststring { get; set; }

        public string mynextstring { get; set; }

        public void test()
        {

        }

        public int get1 { get { return 1; } }

        //public TestClass2 testClass2 { get; set; }
    }

And then tha calling code:

            TestClass tc = new TestClass()
            {
                //testClass2 = new TestClass2(),
                teststring = "test2123",
                mynextstring = "31"

            };

            var t = new TestClass();
            CopyClass<TestClass>(tc, t);
            Console.WriteLine(t.teststring);
            Console.WriteLine(t.mynextstring);
            //Console.WriteLine(t.testClass2.teststring);

            Console.ReadLine();

Okay, so that works; however, you’ll notice that I’ve included and commented out an external class reference. If you include this, then it will copy the class reference (not the class). What if we want to use this to copy child classes?

Actually, it’s not too complicated:

        private static void CopyClass<T>(T copyFrom, T copyTo, bool copyChildren)
        {
            if (copyFrom == null || copyTo == null)
                throw new Exception("Must not specify null parameters");

            var properties = copyFrom.GetType().GetProperties();

            foreach (var p in properties.Where(prop => prop.CanRead && prop.CanWrite))
            {
                if (p.PropertyType.IsClass && p.PropertyType != typeof(string))
                {
                    if (!copyChildren) continue;

                    var destinationClass = Activator.CreateInstance(p.PropertyType);
                    object copyValue = p.GetValue(copyFrom);

                    CopyClass(copyValue, destinationClass, copyChildren);

                    p.SetValue(copyTo, destinationClass);                  
                }
                else
                {
                    object copyValue = p.GetValue(copyFrom);
                    p.SetValue(copyTo, copyValue);
                }
            }
        }

There’s a couple of things to note here: firstly, we need to check if the value is a class, but exclude strings as a special case (I couldn’t find a neater way of doing this); secondly, create the destination class using reflection and cache the source value. Finally, we just recursively call the function, using generic type inference in order to supply the type (which we don’t have as a generic at this point).

If you now just uncomment out the references to TestClass2 it should recursively copy the class.

I have to be honest and say that I’m not too happy with the check for a string type, but other than that, this is quite a neat little way to copy a class.