简体   繁体   中英

C# recursive reflection : EF Model to Viewmodel (Deep) > Property set method not found

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

在此处输入图片说明

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); 

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM