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));
        }
        internal static string GetFastDeepClonerIdentifier(this object o)
        {
            if (o == null)
            {
                return(null);
            }
            var type = o.GetType();
            var p    = CachedFastDeepClonerIdentifier.ContainsKey(type) ? CachedFastDeepClonerIdentifier[type] : CachedFastDeepClonerIdentifier.GetOrAdd(type, DeepCloner.GetFastDeepClonerProperties(type).FirstOrDefault(x => x.FastDeepClonerPrimaryIdentifire));

            return(p == null ? null : type.FullName + type.Name + p.Name + p.FullName + p.GetValue(o));
        }
        internal static Type GetFastType(this string typeName, string assembly)
        {
            if (string.IsNullOrEmpty(assembly))
            {
                throw new Exception("AssemblyName cannot be empty");
            }

            if (!assembly.ToLower().EndsWith(".dll"))
            {
                assembly += ".dll";
            }
            var key = typeName + assembly;

            if (CachedStringTypes.ContainsKey(key))
            {
                return(CachedStringTypes.Get(key));
            }

            var type = Type.GetType($"{typeName}, {assembly.Substring(0, assembly.ToLower().IndexOf(".dll"))}");

            if (type != null)
            {
                if (!CachedAssembly.ContainsKey(assembly))
                {
                    CachedAssembly.TryAdd(assembly, type.Assembly);
                }
                return(CachedStringTypes.GetOrAdd(key, type));
            }
            else
            if (!CachedAssembly.ContainsKey(assembly))
            {
                CachedAssembly.TryAdd(assembly, Assembly.LoadFrom(assembly));
            }

            return(CachedStringTypes.GetOrAdd(key, CachedAssembly.Get(assembly).GetType(typeName, true, true)));
        }
        internal static ConstructorInfo GetConstructorInfo(this Type type, params object[] parameters)
        {
            var key = type.FullName + string.Join("", parameters?.Select(x => x.GetType()));

            if (ConstructorInfos.ContainsKey(key))
            {
                return(ConstructorInfos.Get(key));
            }
#if !NETSTANDARD1_3
            return(ConstructorInfos.GetOrAdd(key, parameters == null ? type.GetConstructor(Type.EmptyTypes) : type.GetConstructor(parameters.Select(x => x.GetType()).ToArray())));
#else
            ConstructorInfo constructor = null;

            foreach (var cr in type.GetTypeInfo().DeclaredConstructors)
            {
                var index = 0;
                var args  = cr.GetParameters();
                if (args.Length == parameters.Length)
                {
                    var apply = true;
                    foreach (var pr in args)
                    {
                        var prType    = pr.ParameterType;
                        var paramType = parameters[index].GetType();

                        if (prType != paramType)
                        {
                            try
                            {
                                Convert.ChangeType(parameters[index], prType);
                            }
                            catch
                            {
                                apply = false;
                                break;
                            }
                        }
                        index++;
                    }
                    if (apply)
                    {
                        constructor = cr;
                    }
                }
            }
            return(ConstructorInfos.GetOrAdd(key, constructor));
#endif
        }
Example #7
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;
                }
            }
        }
Example #10
0
        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);
        }
        internal static object Creator(this Type type, bool validateArgs = true, params object[] parameters)
        {
            try
            {
                var key         = type.FullName + string.Join("", parameters?.Select(x => x.GetType().FullName));
                var constructor = type.GetConstructorInfo(parameters ?? new object[0]);
                if (constructor == null && parameters?.Length > 0)
                {
                    constructor = type.GetConstructorInfo(new object[0]);
                }
                if (constructor != null)
                {
                    var constParam = constructor.GetParameters();
                    if (validateArgs && (parameters?.Any() ?? false))
                    {
                        for (var i = 0; i < parameters.Length; i++)
                        {
                            if (constParam.Length <= i)
                            {
                                continue;
                            }
                            if (constParam[i].ParameterType != parameters[i].GetType())
                            {
                                try
                                {
                                    parameters[i] = Convert.ChangeType(parameters[i], constParam[i].ParameterType);
                                }
                                catch
                                {
                                    // Ignore
                                }
                            }
                        }
                    }

#if NETSTANDARD2_0 || NETSTANDARD1_3 || NETSTANDARD1_5
                    if (!constParam.Any())
                    {
                        if (CachedConstructor.ContainsKey(key))
                        {
                            return(CachedConstructor[key]());
                        }
                    }
                    else if (CachedConstructorWithParameter.ContainsKey(key))
                    {
                        return(CachedConstructorWithParameter[key](parameters));
                    }

                    if (!(parameters?.Any() ?? false))
                    {
                        return(CachedConstructor.GetOrAdd(key, Expression.Lambda <Func <object> >(Expression.New(type)).Compile())());
                    }
                    else
                    {
                        // Create a single param of type object[].
                        ParameterExpression param = Expression.Parameter(typeof(object[]), "args");

                        // Pick each arg from the params array and create a typed expression of them.
                        Expression[] argsExpressions = new Expression[constParam.Length];

                        for (int i = 0; i < constParam.Length; i++)
                        {
                            Expression index            = Expression.Constant(i);
                            Type       paramType        = constParam[i].ParameterType;
                            Expression paramAccessorExp = Expression.ArrayIndex(param, index);
                            Expression paramCastExp     = Expression.Convert(paramAccessorExp, paramType);
                            argsExpressions[i] = paramCastExp;
                        }


                        return(CachedConstructorWithParameter.GetOrAdd(key, Expression.Lambda <Func <object[], object> >(Expression.New(constructor, argsExpressions), param).Compile())(parameters));
                    }
#else
                    if (!constParam.Any())
                    {
                        if (CachedDynamicMethod.ContainsKey(key))
                        {
                            return(CachedDynamicMethod[key]());
                        }
                    }
                    else if (CachedDynamicMethodWithParameters.ContainsKey(key))
                    {
                        return(CachedDynamicMethodWithParameters[key](parameters));
                    }

                    lock (CachedDynamicMethod)
                    {
                        var dynamicMethod = new System.Reflection.Emit.DynamicMethod("CreateInstance", type, (constParam.Any() ? new Type[] { typeof(object[]) } : Type.EmptyTypes), true);
                        System.Reflection.Emit.ILGenerator ilGenerator = dynamicMethod.GetILGenerator();


                        if (constructor.GetParameters().Any())
                        {
                            for (int i = 0; i < constParam.Length; i++)
                            {
                                Type paramType = constParam[i].ParameterType;
                                ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);    // Push array (method argument)
                                ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, i);  // Push i
                                ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref); // Pop array and i and push array[i]
                                if (paramType.IsValueType)
                                {
                                    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Unbox_Any, paramType); // Cast to Type t
                                }
                                else
                                {
                                    ilGenerator.Emit(System.Reflection.Emit.OpCodes.Castclass, paramType); //Cast to Type t
                                }
                            }
                        }


                        //ilGenerator.Emit(System.Reflection.Emit.OpCodes.Nop);
                        ilGenerator.Emit(System.Reflection.Emit.OpCodes.Newobj, constructor);
                        //ilGenerator.Emit(System.Reflection.Emit.OpCodes.Stloc_1); // nothing
                        ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ret);

                        if (!constParam.Any())
                        {
                            return(CachedDynamicMethod.GetOrAdd(key, (ObjectActivator)dynamicMethod.CreateDelegate(typeof(ObjectActivator)))());
                        }
                        else
                        {
                            return(CachedDynamicMethodWithParameters.GetOrAdd(key, (ObjectActivatorWithParameters)dynamicMethod.CreateDelegate(typeof(ObjectActivatorWithParameters)))(parameters));
                        }
                    }
#endif
                }
                else
                {
#if !NETSTANDARD1_3
                    return(FormatterServices.GetUninitializedObject(type));
#else
                    try
                    {
                        if (CachedConstructor.ContainsKey(key))
                        {
                            return(CachedConstructor[key]());
                        }
                        return(CachedConstructor.GetOrAdd(key, Expression.Lambda <Func <object> >(Expression.New(type)).Compile())());
                    }
                    catch
                    {
                        throw new Exception("DeepClonerError: Default constructor is require for NETSTANDARD1_3 for type " + type.FullName);
                    }
#endif
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        internal static ConstructorInfo GetConstructorInfo(this Type type, params object[] parameters)
        {
            IEnumerable <ConstructorInfo> constructors;
            var key = type.FullName + string.Join("", parameters?.Select(x => x.GetType()));

            if (ConstructorInfo.ContainsKey(key))
            {
                return(ConstructorInfo.Get(key));
            }

#if !NETSTANDARD1_3
            constructors = type.GetConstructors();
#else
            constructors = type.GetTypeInfo().DeclaredConstructors;
#endif
            ConstructorInfo constructor = null;
            foreach (var cr in constructors)
            {
                var index = 0;
                var args  = cr.GetParameters();
                if (args.Length == parameters.Length)
                {
                    var apply = true;
                    foreach (var pr in args)
                    {
                        var prType    = pr.ParameterType;
                        var paramType = parameters[index].GetType();

                        if (prType != paramType)
                        {
                            try
                            {
                                if ((prType.IsInternalType() && paramType.IsInternalType()))
                                {
                                    Convert.ChangeType(parameters[index], prType);
                                }
                                else
                                {
                                    if (prType.GetTypeInfo().IsInterface&& paramType.GetTypeInfo().IsAssignableFrom(prType.GetTypeInfo()))
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        apply = false;
                                        break;
                                    }
                                }
                            }
                            catch
                            {
                                apply = false;
                                break;
                            }
                        }
                        index++;
                    }
                    if (apply)
                    {
                        constructor = cr;
                    }
                }
            }

            return(ConstructorInfo.GetOrAdd(key, constructor));
        }