Reputation: 59
I've a base class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassPropertyTest
{
public class BaseClass
{
public string name { get; set; }
public double value { get; set; }
}
}
Then I've some class that derive from the base class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassPropertyTest
{
public class ClassA : BaseClass
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassPropertyTest
{
public class ClassB : BaseClass
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassPropertyTest
{
public class ClassC : BaseClass
{
}
}
I also have a masterclass that has properties to instances of each class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassPropertyTest
{
public class MasterClass
{
public ClassA ClassA { get; set; }
public ClassB ClassB { get; set; }
public ClassC ClassC { get; set; }
}
}
Now when I receive a instance of the masterclass, I need to create a new class from the property ClassA. I use reflection but I keep getting errors that the target is not valid.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ClassPropertyTest
{
class Program
{
static void Main(string[] args)
{
//Fill master class
MasterClass o_masterclass = new MasterClass();
o_masterclass.ClassA = new ClassA { name = "classA", value = 1 };
o_masterclass.ClassB = new ClassB { name = "classB", value = 2 };
o_masterclass.ClassC = new ClassC { name = "classc", value = 3 };
//Now get class by property name
foreach (PropertyInfo prop in o_masterclass.GetType().GetProperties())
{
//Check for class A property
if (prop.Name == "ClassA") {
//Create an instance of that type from ClassA
BaseClass instance = (BaseClass)Activator.CreateInstance(prop.PropertyType.BaseType);
//Copy properties from masterclass property ClassA to new instance of BaseClass
CopyObject<BaseClass>(prop.PropertyType.BaseType, ref instance);
}
}
Console.ReadKey();
}
/// <summary>
/// Copy an object to destination object, only matching fields will be copied
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sourceObject">An object with matching fields of the destination object</param>
/// <param name="destObject">Destination object, must already be created</param>
public static void CopyObject<T>(Type sourceObject, ref T destObject)
{
// If either the source, or destination is null, return
if (sourceObject == null || destObject == null)
return;
// Get the type of each object
Type sourceType = sourceObject;//.GetType();
Type targetType = destObject.GetType();
// Loop through the source properties
foreach (PropertyInfo p in sourceType.GetProperties())
{
// Get the matching property in the destination object
PropertyInfo targetObj = targetType.GetProperty(p.Name);
// If there is none, skip
if (targetObj == null)
continue;
// Set the value in the destination
targetObj.SetValue(destObject, p.GetValue(sourceObject, null), null);
}
}
}
}
Can anyone help me out here? Thanks.
@Sergey, I've changed the CopyObject method to this:
public static void CopyObject<T>(T sourceObject, ref T destObject)
{
// If either the source, or destination is null, return
if (sourceObject == null || destObject == null)
return;
// Get the type of each object
Type sourceType = sourceObject.GetType();
Type targetType = destObject.GetType();
// Loop through the source properties
foreach (PropertyInfo p in sourceType.GetProperties())
{
// Get the matching property in the destination object
PropertyInfo targetObj = targetType.GetProperty(p.Name);
// If there is none, skip
if (targetObj == null)
continue;
// Set the value in the destination
targetObj.SetValue(destObject, p.GetValue(sourceObject, null), null);
}
}
When I call it like you told me it works.
CopyObject<BaseClass>(o_masterclass.ClassA, ref instance);
But in my situation o_masterclass.ClassA actually is prop.PropertyType.BaseType. How can I convert this type to the desired object?
Upvotes: 2
Views: 1497
Reputation: 236188
You can use AutoMapper for that (or other mapping library):
var otherA = Mapper.Map<ClassA>(o_masterclass.ClassA);
By default it maps properties by name. So you even don't need to setup any configurations in this case.
In your solution you should pass sourceObject instead of it's type:
public static void CopyObject<T>(T sourceObject, ref T destObject)
{
if (sourceObject == null || destObject == null)
return;
// Get the type of each object
Type sourceType = sourceObject.GetType();
Type targetType = destObject.GetType();
// Loop through the source properties
foreach (PropertyInfo sourceProp in sourceType.GetProperties())
{
// Get the matching property in the destination object
PropertyInfo destProp = targetType.GetProperty(sourceProp.Name);
// If there is none, skip
if (destProp == null)
continue;
// Set the value in the destination
object value = sourceProp.GetValue(sourceObject, null);
destProp.SetValue(destObject, value, null);
}
}
And call it this way:
CopyObject<BaseClass>(o_masterclass.ClassA, ref instance);
Also keep in mind that type can contain indexers or read-only properties.
Upvotes: 3