1/// <summary>
2 /// Allows one complex type to be converted to another, if both the property name and type match.
3 /// </summary>
4 /// <remarks>
5 /// http://en.wikipedia.org/wiki/Transmogrifier
6 /// </remarks>
7 public class TypeTransmogrifier
8 {
9 /// <summary>
10 /// Allows one complex type to be converted to another, if both the property name and type match.
11 /// </summary>
12 /// <remarks>
13 /// The target type must have a default contructor with no arguments, if it doesn't use the other method which allows contrustor args.
14 ///
15 /// Note that the names must match exactly, yes it's case-sensitive. Also the properties must be public and have get and set accessors, so
16 /// pretty much the same requirements as for XML Serialisation.
17 /// </remarks>
18 /// <param name="source"></param>
19 /// <param name="targetType"></param>
20 /// <returns></returns>
21 public static object Transmogrify( object source, Type targetType )
22 {
23 return Transmogrify( source, targetType, new object[] { } );
24 }
25 /// <summary>
26 /// Allows one complex type to be converted to another, if both the property name and type match.
27 /// </summary>
28 /// <remarks>
29 /// Note that the names must match exactly, yes it's case-sensitive. Also the properties must be public and have get and set accessors, so
30 /// pretty much the same requirements as for XML Serialisation.
31 /// </remarks>
32 /// <param name="source"></param>
33 /// <param name="targetType"></param>
34 /// <param name="constructorArgs"></param>
35 /// <returns></returns>
36 public static object Transmogrify( object source, Type targetType, params object[] constructorArgs )
37 {
38 Type sourceType = source.GetType();
39
40 //Get the properties of both types.
41
42 PropertyInfo[] sourceTypeProperties = sourceType.GetProperties();
43
44 PropertyInfo[] targetTypeProperties = targetType.GetProperties();
45
46 //Create an instance of the targetType
47 object target = Activator.CreateInstance( targetType, constructorArgs );
48
49 foreach ( PropertyInfo sourceTypeProperty in sourceTypeProperties )
50 {
51 foreach ( PropertyInfo targetTypeProperty in targetTypeProperties )
52 {
53 if ( sourceTypeProperty.Name == targetTypeProperty.Name &&
54 sourceTypeProperty.PropertyType == targetTypeProperty.PropertyType )
55 {
56 object sourcePropertyValue = sourceType.InvokeMember(
57 sourceTypeProperty.Name,
58 BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
59 null,
60 source,
61 new object[] { } );
62
63 targetType.InvokeMember(
64 targetTypeProperty.Name,
65 BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty,
66 null,
67 target,
68 new object[] { sourcePropertyValue } );
69 }
70 }
71 }
72
73 return target;
74 }
75 }