internal static object CloneClassInternal(object obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }

            var cloner = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(obj.GetType(), t => GenerateCloner(t, true));

            // safe ojbect
            if (cloner == null)
            {
                return(obj);
            }

            // loop
            var knownRef = state.GetKnownRef(obj);

            if (knownRef != null)
            {
                return(knownRef);
            }

            return(cloner(obj, state));
        }
        private static object CloneClassRoot(object obj)
        {
            if (obj == null)
            {
                return(null);
            }

            var cloner = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(obj.GetType(), t => GenerateCloner(t, true));

            // null -> should return same type
            if (cloner == null)
            {
                return(obj);
            }

            return(cloner(obj, new DeepCloneState()));
        }
 internal static Func <T, DeepCloneState, T> GetClonerForValueType <T>()
 {
     return((Func <T, DeepCloneState, T>)DeepClonerCache.GetOrAddStructAsObject(typeof(T), t => GenerateCloner(t, false)));
 }