internal object Clone(object objectToBeCloned) { if (objectToBeCloned == null) { return(null); } var primaryType = objectToBeCloned.GetType(); if (primaryType.IsArray && primaryType.GetArrayRank() > 1) { return(((Array)objectToBeCloned).Clone()); } if (objectToBeCloned.IsInternalObject()) { return(objectToBeCloned); } object resObject; if (primaryType.IsArray || (objectToBeCloned as IList) != null) { resObject = primaryType.IsArray ? Array.CreateInstance(primaryType.GetIListType(), (objectToBeCloned as Array).Length) : Activator.CreateInstance(primaryType.GetIListType()); var i = 0; var ilist = resObject as IList; var array = resObject as Array; foreach (var item in (objectToBeCloned as IList)) { object clonedIteam = null; if (item != null) { clonedIteam = item.GetType().IsInternalType() ? item : Clone(item); } if (!primaryType.IsArray) { ilist?.Add(clonedIteam); } else { array?.SetValue(clonedIteam, i); } i++; } foreach (var prop in FastDeepClonerCachedItems.GetFastDeepClonerProperties(primaryType).Where(x => !FastDeepClonerCachedItems.GetFastDeepClonerProperties(typeof(List <string>)).Any(a => a.Key == x.Key))) { var property = prop.Value; if (!property.CanRead || property.FastDeepClonerIgnore) { continue; } var value = property.GetValue(objectToBeCloned); if (value == null) { continue; } var clonedIteam = value.GetType().IsInternalType() ? value : Clone(value); property.SetValue(resObject, clonedIteam); } } else if (objectToBeCloned is IDictionary) { resObject = Activator.CreateInstance(primaryType); var resDic = resObject as IDictionary; var dictionary = (IDictionary)objectToBeCloned; foreach (var key in dictionary.Keys) { var item = dictionary[key]; object clonedIteam = null; if (item != null) { clonedIteam = item.GetType().IsInternalType() ? item : Clone(item); } resDic?.Add(key, clonedIteam); } } else if (primaryType.IsAnonymousType()) // dynamic types { var props = FastDeepClonerCachedItems.GetFastDeepClonerProperties(primaryType); resObject = new ExpandoObject(); var d = resObject as IDictionary <string, object>; foreach (var prop in props.Values) { var item = prop.GetValue(objectToBeCloned); var value = item == null || prop.IsInternalType || (item?.IsInternalObject() ?? true) ? item : Clone(item); if (!d.ContainsKey(prop.Name)) { d.Add(prop.Name, value); } } } else { resObject = ReferenceTypeClone((_settings.FieldType == FieldType.FieldInfo ? FastDeepClonerCachedItems.GetFastDeepClonerFields(primaryType) : FastDeepClonerCachedItems.GetFastDeepClonerProperties(primaryType)), primaryType, objectToBeCloned); if (_settings.FieldType == FieldType.Both) { resObject = ReferenceTypeClone(FastDeepClonerCachedItems.GetFastDeepClonerFields(primaryType).Values.ToList().Where(x => !FastDeepClonerCachedItems.GetFastDeepClonerProperties(primaryType).ContainsKey(x.Name)).ToDictionary(x => x.Name, x => x), primaryType, objectToBeCloned, resObject); } } return(resObject); }
internal object CloneTo(object itemToClone, object CloneToItem) { var identifier = CloneToItem.GetFastDeepClonerIdentifier(); if (identifier != null && _alreadyCloned.ContainsKey(identifier)) { return(_alreadyCloned[identifier]); } if (identifier != null) { _alreadyCloned.Add(identifier, CloneToItem); } var type2 = CloneToItem.GetType(); var props2 = FastDeepClonerCachedItems.GetFastDeepClonerProperties(type2); foreach (var prop2 in props2) { if (!prop2.Value.CanWrite) { continue; } var item = itemToClone; var prop = item.GetType().GetProperty(prop2.Key); foreach (var attr in prop2.Value.GetCustomAttributes <FastDeepClonerColumn>()) { var strSplit = attr.ColumnName.Split('.'); for (var i = 0; i < strSplit.Length; i++) { var p = item.GetType().GetProperty(strSplit[i]); if (p != null) { prop = p; if (i != strSplit.Length - 1) { item = p.GetValue(item); } else { break; } } } } if (prop != null) { var value = prop.GetValue(item); if (value == null) { continue; } if (prop.PropertyType.IsInternalType()) { prop2.Value.SetValue(CloneToItem, FastDeepClonerCachedItems.Value(value, prop2.Value.PropertyType, true)); } else if (prop.PropertyType == prop2.Value.PropertyType) { prop2.Value.SetValue(CloneToItem, value.Clone()); } else if (prop.PropertyType.GetIListType() == prop.PropertyType && prop2.Value.PropertyType.GetIListType() == prop2.Value.PropertyType) // if not list { var value2 = prop2.Value.GetValue(item); if (value2 == null) { value2 = prop2.Value.PropertyType.CreateInstance(); } prop2.Value.SetValue(CloneToItem, CloneTo(value, value2)); } } } return(CloneToItem); }
/// <summary> /// Convert Value from Type to Type /// when fail a default value will be loaded. /// can handle all known types like datetime, time span, string, long etc /// ex /// "1115rd" to int? will return null /// "152" to int? 152 /// </summary> /// <param name="value"></param> /// <param name="datatype">eg typeof(int?)</param> /// <param name="defaultValue"></param> /// <returns></returns> public static object ValueConverter(this object value, Type datatype, object defaultValue = null) { return(FastDeepClonerCachedItems.Value(value, datatype, true, defaultValue)); }
/// <summary> /// Get DefaultValue by type /// </summary> /// <param name="propertyType"></param> /// <param name="defaultValue"></param> /// <returns></returns> public static object ValueByType(this Type propertyType, object defaultValue = null) { return(FastDeepClonerCachedItems.ValueByType(propertyType, defaultValue)); }
/// <summary> /// Convert Value from Type to Type /// when fail a default value will be loaded. /// can handle all known types like datetime, time span, string, long etc /// ex /// "1115rd" to int? will return null /// "152" to int? 152 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="value"></param> /// <param name="defaultValue"></param> /// <returns></returns> public static T ValueConverter <T>(this object value, object defaultValue = null) { return((T)FastDeepClonerCachedItems.Value(value, typeof(T), true, defaultValue)); }
/// <summary> /// This will handle only internal types /// and noneinternal type must be of the same type to be cloned /// </summary> /// <param name="itemToClone"></param> /// <param name="CloneToItem"></param> public static void CloneTo(this object itemToClone, object CloneToItem) { FastDeepClonerCachedItems.CloneTo(itemToClone, CloneToItem); }
/// <summary> /// Get Property by name /// </summary> /// <param name="type"></param> /// <param name="name"></param> /// <returns></returns> public static IFastDeepClonerProperty GetProperty(this Type type, string name) { return(FastDeepClonerCachedItems.GetFastDeepClonerProperties(type).ContainsKey(name) ? FastDeepClonerCachedItems.GetFastDeepClonerProperties(type)[name] : null); }
/// <summary> /// will return propertyInfo from the cached propertyInfo. Get and set value is much faster. /// </summary> /// <param name="type"></param> /// <returns></returns> public static List <IFastDeepClonerProperty> GetFastDeepClonerProperties(this Type type) { return(FastDeepClonerCachedItems.GetFastDeepClonerProperties(type).Values.ToList()); }
/// <summary> /// Clear cached data /// </summary> public static void CleanCachedItems() { FastDeepClonerCachedItems.CleanCachedItems(); }