public void Initialize(IStateManager stateManager, IReferenceManager referenceManager, ISurrogateManager surrogateManager)
        {
            this.stateManager     = stateManager;
            this.referenceManager = referenceManager;
            this.surrogateManager = surrogateManager;
            var tkey   = typeof(TKey);
            var tvalue = typeof(TValue);

            var tkeyIsValueTypeOrStringOrTypeNotStruct = IsValueTypeOrStringOrTypeNotStruct(tkey);
            var tvalueIsValueTypeOrString = IsValueTypeOrStringOrType(tvalue);

            if (tkeyIsValueTypeOrStringOrTypeNotStruct && tvalueIsValueTypeOrString)
            {
                implementation = new DictCase1 <TKey, TValue>();
                CaseType       = 1;
            }
            else if (tkeyIsValueTypeOrStringOrTypeNotStruct &&
                     (typeof(IStateObject).IsAssignableFrom(tvalue) ||
                      TypeCacheUtils.IsIListOrIDictionary(tvalue))


                     )
            {
                implementation = new DictCase2 <TKey, TValue>(stateManager, referenceManager);
                ((DictCase2 <TKey, TValue>)implementation).SetParent(this);
                CaseType = 2;
            }
            else if (tkeyIsValueTypeOrStringOrTypeNotStruct && typeof(Delegate).IsAssignableFrom(tvalue))
            {
                implementation = new DictCase5 <TKey, TValue>(stateManager, surrogateManager);

                CaseType = 5;
            }
            else if (typeof(IStateObject).IsAssignableFrom(tkey) && tvalueIsValueTypeOrString)
            {
                implementation = new DictCase3 <TKey, TValue>();
                CaseType       = 3;
            }
            else if (typeof(IStateObject).IsAssignableFrom(tkey) &&
                     (typeof(IStateObject).IsAssignableFrom(tvalue) || TypeCacheUtils.IsIListOrIDictionary(tvalue))
                     )
            {
                implementation = new DictCase4 <TKey, TValue>();
                CaseType       = 4;
            }
            else if (tkeyIsValueTypeOrStringOrTypeNotStruct && SurrogatesDirectory.IsSurrogateRegistered(tvalue))
            {
                implementation = new DictCase6 <TKey, TValue>(stateManager, surrogateManager, referenceManager);
                ((DictCase6 <TKey, TValue>)implementation).SetParent(this);
                CaseType = 6;
            }
            else
            {
                throw new NotSupportedException();
            }
        }
            public SerializerMethods(JsonReader reader, Type keyType, Type valueType)
            {
                this.reader    = reader;
                this.keyType   = keyType;
                this.valueType = valueType;

                //First assign delegate depending on keyType
                if (typeof(string) == keyType)
                {
                    ReadKeyMethod = ReadInputAsString;
                }
                else if (typeof(Type) == keyType)
                {
                    ReadKeyMethod = ReadInputAsType;
                }
                else if (typeof(IStateObject).IsAssignableFrom(keyType))
                {
                    ReadKeyMethod = ReadInputAsStateObject;
                }
                else if (keyType.IsEnum)
                {
                    ReadKeyMethod = ReadInputAsEnum;
                }
                else
                {
                    ReadKeyMethod = ReadInputAsOther;
                }

                //Second assign delegate depending on valueType
                if (typeof(string) == valueType)
                {
                    ReadValueMethod = ReadInputAsString;
                }
                else if (typeof(Type) == valueType)
                {
                    ReadValueMethod = ReadInputAsType;
                }
                else if (valueType.IsEnum)
                {
                    ReadValueMethod = ReadInputValueAsEnum;
                }
                else if (typeof(IStateObject).IsAssignableFrom(valueType) ||
                         TypeCacheUtils.IsIListOrIDictionary(valueType) ||
                         typeof(Delegate).IsAssignableFrom(valueType) ||
                         SurrogatesDirectory.IsSurrogateRegistered(valueType))
                {
                    ReadValueMethod = ReadInputAsStateObject;
                }
                else
                {
                    ReadValueMethod = ReadInputValueAsOther;
                }
            }
            public SerializerMethods(JsonWriter writer, Type keyType, Type valueType)
            {
                this.writer    = writer;
                this.keyType   = keyType;
                this.valueType = valueType;
                //First assign delegate depending on keyType
                if (typeof(string) == keyType)
                {
                    WriteKeyMethod = WriteKeyGeneric;
                }
                else if (typeof(Type) == keyType)
                {
                    WriteKeyMethod = WriteKeyType;
                }
                else if (typeof(IStateObject).IsAssignableFrom(keyType))
                {
                    WriteKeyMethod = WriteKeyStateObject;
                }
                else
                {
                    WriteKeyMethod = WriteKeyGeneric;
                }

                //Second assign delegate depending on valueType
                if (typeof(string) == valueType)
                {
                    WriteValueMethod = WriteValueGeneric;
                }
                else if (typeof(Type) == valueType)
                {
                    WriteValueMethod = WriteValueType;
                }
                else if (typeof(IStateObject).IsAssignableFrom(valueType) ||
                         TypeCacheUtils.IsIListOrIDictionary(valueType) ||
                         typeof(Delegate).IsAssignableFrom(valueType) ||
                         SurrogatesDirectory.IsSurrogateRegistered(valueType))
                {
                    WriteValueMethod = WriteValueStateObject;
                }
                else
                {
                    WriteValueMethod = WriteValueGeneric;
                }
            }