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));
        }
Beispiel #4
0
        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);
        }