0

I have two objects from this class:

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    public IList<B> Bs { get; set; }
}

public class B
{
    public string Description { get; set; }
    public IList<C> Cs { get; set; }
}

public class C
{
    public string Description { get; set; }
}

Now I want to loop through all the properties of the two object instances with FastMember and copy the properties from object 1 to object 2.

Here's what I got so far (not working!)

// Set accessors
var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);

foreach (var sourceItem in (IList)sourceAccessor.Target)
{
    var targetItemAccessor = ObjectAccessor.Create(targetAccessor.Target);
    var sourceItemAccessor = ObjectAccessor.Create(sourceItem);

    // Overwrite property
    targetItemAccessor[p] = sourceItemAccessor[p];
}

this code is obviously not working...any ideas? Thanks!

Raphael
  • 107
  • 1
  • 9

1 Answers1

0

You can create a shallow copy with the help of the TypeAccessor using something like:

var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);

var access = TypeAccessor.Create(typeof(A));
var members = access.GetMembers();

foreach (var member in members)
{
    targetAccessor[member.Name] = sourceAccessor[member.Name];
}

Have a look at the FastMember tests for usage examples.

For a deep copy, you could check either the property name or use the property type to determine whether to apply a deep copy of lists or if a shallow copy is sufficient.

Edit: Here is an example for a simplified version that recursively copies properties of type IList (see this question on how to determine which property is a list), assuming the source and target object's lists have the same length:

private static void MirrorObject(object object1, object object2)
{
    var sourceAccessor = ObjectAccessor.Create(object1);
    var targetAccessor = ObjectAccessor.Create(object2);

    var access = TypeAccessor.Create(object1.GetType());
    var members = access.GetMembers();

    foreach (var member in members)
    {
        if (member.Type.IsGenericType && (member.Type.GetGenericTypeDefinition() == typeof(IList<>)))
        {
            var list1 = (IList)sourceAccessor[member.Name];
            var list2 = (IList)targetAccessor[member.Name];
            if (list1.Count != list2.Count)
            {
                throw new ArgumentException("Lists need to be of the same length.");
            }
            for (var i = 0; i < list1.Count; ++i)
            {
                MirrorObject(list1[i], list2[i]);
            }
        }
        else
        {
            targetAccessor[member.Name] = sourceAccessor[member.Name];
        }
    }
}
user7217806
  • 2,014
  • 2
  • 10
  • 12
  • Thank you for your answer! Let's say I want to copy the properties recursively, meaning I want to loop throught the `IList` and `IList` and copy those nested properties? – Raphael Sep 30 '19 at 05:12
  • You are welcome, I updated the answer to include an example for that use case. – user7217806 Sep 30 '19 at 22:19
  • I'm currently trying to get this work. But on the `member.Type.IsGenericType && (member.Type.GetGenericTypeDefinition() == typeof(IList<>))` part, it also detects a `String` as list... – Raphael Oct 01 '19 at 05:53
  • I cannot reproduce this, e.g.: `var member = "test"; var isList = member.GetType().IsGenericType && (member.GetType().GetGenericTypeDefinition() == typeof(IList<>));` results in `false`. – user7217806 Oct 01 '19 at 17:13
  • @user7217806 i have almost the same code you use, but i get an exception (NotSupportedException), cand you write to me some hint about usage and errors? more detail here : https://stackoverflow.com/questions/68633228/fastmember-getmembers-throw-not-supported-exception – Skary Aug 03 '21 at 09:25
  • @Skary Did you manage to resolve the issue? – user7217806 Aug 04 '21 at 20:05
  • 1
    @user7217806 yes sorry, i have made a mistake in the code and passed a strange type to fastmember framework (json instance form the newtonsoft JSON framework). I don't know exactily which are difference, but that kind of object is a bit weird, and that is the cause of my problem. So i deleted my question and forgot about this comment. If i use a "normal" object everything work fine, in my scenario only "normal" object have to be managed, so eventually there are no issue. – Skary Aug 05 '21 at 13:55