Thursday, April 22, 2010

C# Copy Property Values between Types


For a recent project, i came across a quite weird requirement. The requirement was to copy Public Property values in TypeA to TypeB. The criteria was that both the types should have the same property names, otherwise those properties will be skipped. The second criteria was that, it should copy nested types contained in a given source type. 


A word of caution. If you have Enums as properties, then both Enums in TypeA as well as in TypeB should share the same numerical values, even if Enum names are different. One more item is that, nested types should have the default constructor, else you should remove the "new()" generic constraint.


You can use this use the code below, if you come across similar sort of requirements. :)

    public static class Converter
    {
        public static void CopyProperties<T, Q>(T Src, Q Dest)
            where T : new()
            where Q : new()
        {
            foreach (PropertyInfo objSrcPI in Src.GetType().GetProperties())
            {
                PropertyInfo objDestPI = Dest.GetType().GetProperty(objSrcPI.Name);
                Object Val = null;

                if (objDestPI != null)
                {
                    if (objDestPI.PropertyType.BaseType == typeof(Enum))
                    {
                        Val = (int)objSrcPI.GetValue(Src, null);
                        Dest.GetType().GetProperty(objSrcPI.Name).SetValue(Dest, Val, null);
                    }
                    else if (objDestPI.PropertyType == objSrcPI.PropertyType)
                    {
                        Val = objSrcPI.GetValue(Src, null);
                        Dest.GetType().GetProperty(objSrcPI.Name).SetValue(Dest, Val, null);
                    }
                    else if (objDestPI.PropertyType != objSrcPI.PropertyType)
                    {
                        if (!objDestPI.PropertyType.IsValueType &&
                            !objDestPI.PropertyType.IsPrimitive &&
                            objSrcPI.GetValue(Src, null) != null)
                        {
                            Type objDestType = objDestPI.PropertyType;
                            Object objDest = Activator.CreateInstance(objDestType);
                            Val = objSrcPI.GetValue(Src, null);
                            CopyProperties(Val, objDest);
                            Dest.GetType().GetProperty(objSrcPI.Name).SetValue(Dest, objDest, null);
                        }
                    }
                }
            }
        }
    }

Using the CopyProperties procedure

    class A
    {
        public string FirstName { get; set; }
        public int Age { get; set; }
    }

    class B
    {
        public string FirstName { get; set; }
        public int Age { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            A objA = new A();
            B objB = new B();

            objA.FirstName = "Alpha";
            objA.Age = 12;

            Converter.CopyProperties(objA,objB);
        }
    }


No comments: