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 Father
andClass Son
, each one with several properties (string, int, enum, etc..) - In my class
Father
I have a list ofSons
- I have a MVC form that submits/returns a full object
Father
withSon
entries ==> objectobj
- Somewhere in the code I am loading the actual father from the DB (including the sons) -> object
original
- variable
parameters
represents 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