/// <summary>
        /// Register (add) a type handler for a type and dbType
        /// </summary>
        /// <param name="type">the type</param>
        /// <param name="dbType">the dbType (optional, if dbType is null the handler will be used for all dbTypes)</param>
        /// <param name="handler">the handler instance</param>
        public void Register(Type type, string dbType, ITypeHandler handler)
        {
            HybridDictionary map = (HybridDictionary)_typeHandlerMap[type];

            if (map == null)
            {
                map = new HybridDictionary();
                _typeHandlerMap.Add(type, map);
            }
            if (dbType == null)
            {
                if (_logger.IsInfoEnabled)
                {
                    // notify the user that they are no longer using one of the built-in type handlers
                    ITypeHandler oldTypeHandler = (ITypeHandler)map[NULL];

                    if (oldTypeHandler != null)
                    {
                        // the replacement will always(?) be a CustomTypeHandler
                        CustomTypeHandler customTypeHandler = handler as CustomTypeHandler;

                        string replacement = string.Empty;

                        if (customTypeHandler != null)
                        {
                            // report the underlying type
                            replacement = customTypeHandler.Callback.ToString();
                        }
                        else
                        {
                            replacement = handler.ToString();
                        }

                        // should oldTypeHandler be checked if its a CustomTypeHandler and if so report the Callback property ???
                        _logger.Info("Replacing type handler [" + oldTypeHandler.ToString() + "] with [" + replacement + "].");
                    }
                }

                map[NULL] = handler;
            }
            else
            {
                map.Add(dbType, handler);
            }
        }
        /// <summary>
        /// Deserialize a TypeHandler object
        /// </summary>
        /// <param name="node"></param>
        /// <param name="configScope"></param>
        /// <returns></returns>
        public static void Deserialize(XmlNode node, ConfigurationScope configScope)
        {
            TypeHandler handler = new TypeHandler();

            NameValueCollection prop = NodeUtils.ParseAttributes(node, configScope.Properties);
            handler.CallBackName = NodeUtils.GetStringAttribute(prop, "callback");
            handler.ClassName = NodeUtils.GetStringAttribute(prop, "type");
            handler.DbType = NodeUtils.GetStringAttribute(prop, "dbType");

            handler.Initialize();

            configScope.ErrorContext.MoreInfo = "Check the callback attribute '" + handler.CallBackName + "' (must be a classname).";
            ITypeHandler typeHandler = null;
            Type type = configScope.SqlMapper.TypeHandlerFactory.GetType(handler.CallBackName);
            object impl = Activator.CreateInstance( type );
            if (impl is ITypeHandlerCallback)
            {
                typeHandler = new CustomTypeHandler((ITypeHandlerCallback) impl);
            }
            else if (impl is ITypeHandler)
            {
                typeHandler = (ITypeHandler) impl;
            }
            else
            {
                throw new ConfigurationException("The callBack type is not a valid implementation of ITypeHandler or ITypeHandlerCallback");
            }

            //
            configScope.ErrorContext.MoreInfo = "Check the type attribute '" + handler.ClassName + "' (must be a class name) or the dbType '" + handler.DbType + "' (must be a DbType type name).";
            if (handler.DbType!= null && handler.DbType.Length > 0)
            {
                configScope.DataExchangeFactory.TypeHandlerFactory.Register(TypeUtils.ResolveType(handler.ClassName), handler.DbType, typeHandler);
            }
            else
            {
                configScope.DataExchangeFactory.TypeHandlerFactory.Register(TypeUtils.ResolveType(handler.ClassName), typeHandler);
            }
        }
        public void Register(Type type, string dbType, ITypeHandler handler)
        {
            HybridDictionary dictionary = (HybridDictionary)this._typeHandlerMap[type];

            if (dictionary == null)
            {
                dictionary = new HybridDictionary();
                this._typeHandlerMap.Add(type, dictionary);
            }
            if (dbType == null)
            {
                if (_logger.IsInfoEnabled)
                {
                    ITypeHandler handler2 = (ITypeHandler)dictionary["_NULL_TYPE_"];
                    if (handler2 != null)
                    {
                        CustomTypeHandler handler3 = handler as CustomTypeHandler;
                        string            str      = string.Empty;
                        if (handler3 != null)
                        {
                            str = handler3.Callback.ToString();
                        }
                        else
                        {
                            str = handler.ToString();
                        }
                        _logger.Info("Replacing type handler [" + handler2.ToString() + "] with [" + str + "].");
                    }
                }
                dictionary["_NULL_TYPE_"] = handler;
            }
            else
            {
                dictionary.Add(dbType, handler);
            }
        }