internal static Type GetIListItemType(this Type type) { if (CachedIListInternalTypes.ContainsKey(type)) { return(CachedIListInternalTypes[type]); } if (type.IsArray) { CachedIListInternalTypes.Add(type, type.GetElementType()); } else { if (type.GenericTypeArguments.Any()) { CachedIListInternalTypes.Add(type, type.GenericTypeArguments.First()); } else if (type.FullName.Contains("List`1") || type.FullName.Contains("ObservableCollection`1")) { CachedIListInternalTypes.Add(type, typeof(List <>).MakeGenericType(type.GetRuntimeProperty("Item").PropertyType)); } else { CachedIListInternalTypes.Add(type, type); } } return(CachedIListInternalTypes[type]); }
internal static object ConvertToInterface(this Type interfaceType, object item) { var type = item.GetType(); if (interfaceType.IsAssignableFrom(type)) { return(item); } var props = DeepCloner.GetFastDeepClonerProperties(type); var args = new SafeValueType <string, object>(); foreach (var iProp in DeepCloner.GetFastDeepClonerProperties(interfaceType)) { var p = DeepCloner.GetProperty(type, iProp.Name); if (p == null) { continue; } var value = p.GetValue(item); if (value == null || p.PropertyType == iProp.PropertyType) { args.Add(iProp.Name, value); continue; } try { if (iProp.PropertyType.IsInterface) { args.Add(iProp.Name, iProp.PropertyType.InterFaceConverter(value)); } else { args.Add(iProp.Name, Convert.ChangeType(value, DeepCloner.GetProperty(interfaceType, p.Name).PropertyType)); } } catch (Exception e) { var iType = iProp.PropertyType; throw new Exception($"Property {p.Name} has different type then the interface which is of type {iProp.PropertyType}. \n (Convert.ChangeType) could not convert from {p.PropertyType} to {iType}. \n Orginal Exception: {e.Message}"); } } var key = $"{(type.IsAnonymousType() ? string.Join(" | ", props.Select(x => x.FullName).ToArray()) : type.FullName)} | {interfaceType.FullName}"; var newtype = CachedConvertedObjectToInterface.ContainsKey(key) ? CachedConvertedObjectToInterface[key] : CachedConvertedObjectToInterface.GetOrAdd(key, FastDeepCloner.ConvertToInterfaceTypeGenerator.Convert(interfaceType, type)); var returnValue = Creator(newtype, false, args.Values.ToArray()); var constructor = GetConstructorInfo(newtype, args.Values.ToArray()); if (constructor == null) { foreach (var p in args) { DeepCloner.GetProperty(newtype, p.Key).SetValue(returnValue, args[p.Key]); } } return(returnValue); }
internal static Dictionary <string, IFastDeepClonerProperty> GetFastDeepClonerProperties(this Type primaryType, ICollection <PropertyInfo> ignorePropertyInfos = null) { ignorePropertyInfos = ignorePropertyInfos ?? new PropertyInfo[0]; if (!CachedPropertyInfo.ContainsKey(primaryType) && ignorePropertyInfos.None()) { CachedPropertyInfo.Add(primaryType, GetPropertiesInternal(primaryType, ignorePropertyInfos)); } return(ignorePropertyInfos.None() ? CachedPropertyInfo[primaryType] : GetPropertiesInternal(primaryType, ignorePropertyInfos)); }
private object ReferenceTypeClone(Dictionary <string, IFastDeepClonerProperty> properties, Type primaryType, object objectToBeCloned, object appendToValue = null) { var identifier = objectToBeCloned.GetFastDeepClonerIdentifier(); if (identifier != null && _alreadyCloned.ContainsKey(identifier)) { return(_alreadyCloned[identifier]); } var resObject = appendToValue ?? _settings.OnCreateInstance(primaryType); if (identifier != null) { _alreadyCloned.Add(identifier, resObject); } foreach (var property in properties.Values) { if (!property.CanRead || property.FastDeepClonerIgnore) { continue; } var value = property.GetValue(objectToBeCloned); if (value == null) { continue; } if ((property.IsInternalType || value.GetType().IsInternalType())) { property.SetValue(resObject, value); } else { if (_settings.CloneLevel == CloneLevel.FirstLevelOnly) { continue; } property.SetValue(resObject, Clone(value)); } } return(resObject); }
internal static Dictionary <string, IFastDeepClonerProperty> GetFastDeepClonerProperties(this Type primaryType) { if (!CachedPropertyInfo.ContainsKey(primaryType)) { var properties = new SafeValueType <string, IFastDeepClonerProperty>(); if (primaryType.GetTypeInfo().BaseType != null && primaryType.GetTypeInfo().BaseType.Name != "Object") { primaryType.GetRuntimeProperties().Where(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))).ToList(); primaryType.GetTypeInfo().BaseType.GetRuntimeProperties().Where(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))).ToList(); } else { primaryType.GetRuntimeProperties().Where(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))).ToList(); } CachedPropertyInfo.Add(primaryType, properties); } return(CachedPropertyInfo[primaryType]); }
internal static INotifyPropertyChanged ProxyCreator(this Type type) { lock (ProxyTypes) { try { MethodInfo method; if (ProxyTypesPropertyChanged.ContainsKey(type)) { method = ProxyTypesPropertyChanged[type]; } else { method = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.GetParameters().Any(a => a.ParameterType == typeof(object)) && x.GetParameters().Any(a => a.ParameterType == typeof(PropertyChangedEventArgs))); ProxyTypesPropertyChanged.TryAdd(type, method); } INotifyPropertyChanged item; if (ProxyTypes.ContainsKey(type)) { item = ProxyTypes[type].Creator() as INotifyPropertyChanged; } else { ProxyTypes.Add(type, INotifyPropertyChangedProxyTypeGenerator.GenerateProxy(type)); item = ProxyTypes[type].Creator() as INotifyPropertyChanged; } if (method != null) { item.PropertyChanged += (PropertyChangedEventHandler)Delegate.CreateDelegate(typeof(PropertyChangedEventHandler), item, method); } return(item); } catch (Exception e) { throw e; } } }
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); }