1

when I try to set Properties of a child Class I receive this error:

Additional information: Property set method not found.

Can anyone shed some light on this? - Clearly they have setters, see img below

enter image description here

Classes:

public class Test
{
    public string Name {get;set}
    public LetterGrade Grade {get;set;}
}

pulic class LetterGrade
{
    public string Name {get;set;}
    public double GradePercentage {Get;set;}
}

Use:

var dbModel = context.Test.FirstOrDefault(w=>w.ID == ID)
this.Bind(dbModel);

Here is how i have been calling children (just fine) but would rather just make 1 call (recursively) Some more complex objects will have children of children and so on

this.LetterGrade.Bind(dbModel.LetterGrade); 
Pakk
  • 1,299
  • 2
  • 18
  • 36
  • 2
    *Does* the property that throws the exception have a `setter`? – haim770 Feb 16 '16 at 07:14
  • 1
    Why are you also not using some library like AutoMapper for this? – Red Feb 16 '16 at 15:00
  • @raderick I've heard that automapper is a bit slow regarding the overhead just to move copy 1 object to another. – Pakk Feb 16 '16 at 15:33
  • @haim770 From what I've seen, from this code, no. However is a property on my main class that I am passing into the above function as destination and their properties are public? I'll edit in some classes for reference. – Pakk Feb 16 '16 at 15:35
  • Hmmm it looks like in your generic code you should not bind property to property (`destProperty.Bind(sourceProperty)`), but instead map values of both properties to each other, creating new instance of an object if it's null in destination property. OR you should use property value without deep copying, depending on the logic you are trying to achieve. – Red Feb 17 '16 at 06:28
  • @raderick Hey thanks for the comment, I will check into in the morning and let you know if that worked! – Pakk Feb 17 '16 at 06:48

1 Answers1

2

Yes, technically your issue here is that you are trying to bind object of type PropertyInfo to another object of same type.

Also It's not very clear what you try to do here - if source property value is null, you are trying to bind it's value to destination property, which should not happen.

Code should probably re-arranged and depend on what behavior you specifically are trying to achieve: deep copy of reference-types, simple reference copy, how to treat collections, etc...

I modified code a bit to show the idea:

public static void Bind(this object destination, object source)
        {
            if (source != null)
            {
                var destProperties = destination.GetType().GetProperties();
                foreach (var sourceProperty in source.GetType().GetProperties())
                {
                    var availableDestinationProperties = destProperties.Where(x=>x.Name == sourceProperty.Name && x.PropertyType.IsAssignableFrom(sourceProperty.PropertyType));

                    if (availableDestinationProperties.Count() == 0)
                    {
                        continue;
                    }

                    var destProperty = availableDestinationProperties.Single();

                    var sourcePropertyValue = sourceProperty.GetValue(source, null);
                    var destPropertyType = destProperty.PropertyType;    

                    if (sourcePropertyValue != null)
                    {   
                        if (IsCollection(destPropertyType))
                        {
                            //handle collections: either do collection item references copy, do deep copy of each element in collection, etc.. 
                        }

                        if (IsReferenceType(destPropertyType))
                        {
                            //do deep copy with recursion: create object OR do reference copy in case you need this
                        }

                        destProperty.SetValue(destination, sourcePropertyValue, new object[] { });
                    }
                }
            }
        }

With time number of those conditions will grow and you will have to have a lot of tests to verify stuff works fine.

If you write a small-to-medium sized application, you can still use AutoMapper, it's not that slow. If you don't specifically like it, there are other 3rd party libs that can do it - you can see question like this one, for instance: Alternatives to AutoMapper

It looks like it's not worth for you to reinvent the wheel.

Community
  • 1
  • 1
Red
  • 2,728
  • 1
  • 20
  • 22
  • The null not copying is by design as where it is being copied to is always a new object with same properties and therefore already null. Thanks so much for the alternatives page - i've done went through and fell in love with the value injecter usage. (which is what I was shooting for) – Pakk Feb 17 '16 at 22:43