I used Automapper but it was not giving me the full functionality I wanted so I decided to make my custom "ApplyValuesByExcluding" between 2 objects (they even may be from different Classes).
Basically my code is almost done... near but not exactly at 100%.
So I decided to ask you guys some help.
Example:
- Using EF I have 
Class FatherandClass Son, each one with several properties (string, int, enum, etc..) - In my class 
FatherI have a list ofSons - I have a MVC form that submits/returns a full object 
FatherwithSonentries ==> objectobj - Somewhere in the code I am loading the actual father from the DB (including the sons) -> object 
original - variable 
parametersrepresents a string array with the name of the "child" property name, in this case "Sons" (but it could be more...) - I also specify some properties to NOT set the value 
"Id", "RowVersion", "CreatedOn" 
Then I use the following line of code:
MyConversion.ApplyValuesByExcluding(obj, original, parameters, "Id", "RowVersion", "CreatedOn");`
After this I am calling db.SaveChanges(); in a lower layer of the Repository.
At this point I am able to set correctly all the existing properties both from the Father as well of the children....
The problem is:
My reflection code is not affecting the Entity Framework in order to add or remove "Sons"
Here is my code:
public static class MyConversion
    {
        public static void ApplyValuesByExcluding(object source, object target, object parameters, params string[] excludedpropertyNames)
        {
            var typeofT = target.GetType();
            var typeofS = source.GetType();
            var allProperties = typeofT
                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(prop => prop.CanWrite);
            string[] childProperties = null;
            if (parameters != null)
            {
                var valueType = parameters.GetType();
                if (valueType.IsArray && (typeof(string)).IsAssignableFrom(valueType.GetElementType()))
                {
                    childProperties = parameters as string[];
                }
            }
            foreach (var propT in allProperties)
            {
                var propS = typeofS.GetProperty(propT.Name);
                var ptT = propT.PropertyType;
                var ptS = propS.PropertyType;
                if (propS == null || ptT != ptS) continue; // properties do NOT match... 
                if (excludedpropertyNames.Contains(propT.Name)) continue;
                if (ptT.IsPrimitive
                    || ptT == typeof(Decimal)
                    || ptT == typeof(Nullable<Decimal>)
                    || ptT == typeof(Nullable<long>)
                    || ptT == typeof(Nullable<int>)
                    || ptT == typeof(Nullable<bool>)
                    || ptT == typeof(String))
                {
                    propT.SetValue(target, propS.GetValue(source));
                }
                else
                {
                    var u = Nullable.GetUnderlyingType(ptT);
                    if (u != null && u.IsEnum) // Process enum properties
                    {
                        propT.SetValue(target, propS.GetValue(source));
                    }
                    else
                    {
                        // Process child properties
                        if (childProperties != null && ptT.IsGenericType && childProperties.Contains(propT.Name))
                        {
                            var sourceListRaw = propS.GetValue(source);
                            var targetListRaw = propT.GetValue(target);
                            if (sourceListRaw == null || targetListRaw == null) continue; //Something is not right: child list wasn't loaded???
                            var sourceList = ((IEnumerable<dynamic>)sourceListRaw).Select(x => x).ToList();
                            var targetList = ((IEnumerable<dynamic>)targetListRaw).Select(x => x).ToList();
                            var baseListTypeT = ptT.GetGenericArguments()[0];
                            var propertyIdT = baseListTypeT.GetProperty("Id");
                            var baseListTypeS = ptS.GetGenericArguments()[0];
                            var propertyIdS = baseListTypeS.GetProperty("Id");
                            var sourceListIds = sourceList.Select(x => (long)propertyIdS.GetValue(x)).ToArray();
                            var targetListIds = targetList.Select(x => (long)propertyIdT.GetValue(x)).ToArray();
                            var idsToRemove = targetListIds.Where(x => !sourceListIds.Contains(x)).ToArray();
                            targetList.RemoveAll(x => idsToRemove.Contains((long)propertyIdT.GetValue(x))); // NOT WORKING...
                            for (var pos = 0; pos < targetList.Count; pos++)
                            {
                                var element = targetList[pos];
                                var elementId = (long)propertyIdT.GetValue(element);
                                var sourceElement = sourceList.Where(x => (long)propertyIdS.GetValue(x) == elementId).FirstOrDefault();
                                if (sourceElement != null)
                                {
                                    MyConversion.ApplyValuesByExcluding(sourceElement, element, null, excludedpropertyNames); // update element
                                }
                            }
                            // Add new ones (Id == 0)
                            targetList.AddRange(sourceList.Where(x => (long)propertyIdS.GetValue(x) == 0)); // NOT WORKING...                           
                        }
                    }
                }
            }
        }
    }
I would appreciate the help. Thanks
Aucun commentaire:
Enregistrer un commentaire