private Func <object, object> MakeCloner(Type t) { if (t.IsGenericType) { var g = t.GetGenericTypeDefinition(); if (g == typeof(Nullable <>)) { var c = GetCloner(t.GetGenericArguments()[0]); return(src => src ?? c(src)); } } if (t.IsArray) { var e = t.GetElementType(); if (IsCopyable(e)) { if (t.GetArrayRank() > 1) { return(CloneUtils.CloneArrayPrimitiveNDim); } var m = CloneUtils.GetGeneric(nameof(CloneUtils.CloneArrayPrimitive), e); return(CloneUtils.MakeDelegate <Func <object, object> >(m)); } else { var cloneElem = GetCloner(e); if (t.GetArrayRank() > 1) { return(src => CloneUtils.CloneArrayNDim(src, cloneElem)); } var m = CloneUtils.GetGeneric(nameof(CloneUtils.CloneArray), e); var d = CloneUtils.MakeDelegate <Func <object, Func <object, object>, object> >(m); return(src => d(src, cloneElem)); } } { var idict = Utils.GetIDictionary(t); if (idict != null) { var a = idict.GetGenericArguments(); if (!IsCopyable(a[0])) { var сk = GetCloner(a[0]); var сv = GetCloner(a[1]); var m = CloneUtils.GetGeneric(nameof(CloneUtils.CloneIDictionary), t, a[0], a[1]); var d = CloneUtils.MakeDelegate < Func <object, Func <object, object>, Func <object, object>, object> >(m); return(obj => d(obj, сk, сv)); } else if (!IsCopyable(a[1])) { var сv = GetCloner(a[1]); var m = CloneUtils.GetGeneric( nameof(CloneUtils.CloneIDictionaryPrimiviteKey), t, a[0], a[1]); var d = CloneUtils.MakeDelegate <Func <object, Func <object, object>, object> >(m); return(obj => d(obj, сv)); } else { var m = CloneUtils.GetGeneric( nameof(CloneUtils.CloneIDictionaryPrimivite), t, a[0], a[1]); return(CloneUtils.MakeDelegate <Func <object, object> >(m)); } } } if (t == typeof(object)) { return(DeepObject); } if (IsCopyable(t)) { return(CloneUtils.ValueCopy); } var meta = Meta.Get(t, Options); { var icoll = Utils.GetICollection(t); if (icoll != null) { var a = icoll.GetGenericArguments(); if (!IsCopyable(a[0])) { var сe = GetCloner(a[0]); if (meta.SerializeItemIf != null) { var m = CloneUtils.GetGeneric(nameof(CloneUtils.CloneCollectionIf), t, a[0]); var d = CloneUtils.MakeDelegate < Func <object, Func <object, object>, serializeItemIfType, object> >(m); return(obj => d(obj, сe, meta.SerializeItemIf)); } else { var m = CloneUtils.GetGeneric(nameof(CloneUtils.CloneCollection), t, a[0]); var d = CloneUtils.MakeDelegate <Func <object, Func <object, object>, object> >(m); return(obj => d(obj, сe)); } } else { if (meta.SerializeItemIf != null) { var m = CloneUtils.GetGeneric( nameof(CloneUtils.CloneCollectionPrimitiveIf), t, a[0]); var d = CloneUtils.MakeDelegate <Func <object, serializeItemIfType, object> >(m); return(src => d(src, meta.SerializeItemIf)); } else { var m = CloneUtils.GetGeneric( nameof(CloneUtils.CloneCollectionPrimitive), t, a[0]); return(CloneUtils.MakeDelegate <Func <object, object> >(m)); } } } } if (t.IsClass || t.IsInterface || Utils.IsStruct(t)) { var surrogateCloner = MakeSurrogateCloner(meta); if (surrogateCloner != null) { return(surrogateCloner); } var oc = new ObjectCloner(this, meta); return(oc.Get()); } throw new NotImplementedException("Unable to clone type: " + t.FullName); }