public override string ToQuotedString(Type fieldType, object value)
        {
            if (fieldType.HasAttribute<EnumAsIntAttribute>())
            {
                return this.ConvertNumber(fieldType.GetEnumUnderlyingType(), value).ToString();
            }

            if (value is int && !fieldType.IsEnumFlags())
            {
                value = fieldType.GetEnumName(value);
            }

            if (fieldType.IsEnum)
            {
                var enumValue = DialectProvider.StringSerializer.SerializeToString(value);
                // Oracle stores empty strings in varchar columns as null so match that behavior here
                if (enumValue == null)
                    return null;
                enumValue = DialectProvider.GetQuotedValue(enumValue.Trim('"'));
                return enumValue == "''"
                    ? "null"
                    : enumValue;
            }
            return base.ToQuotedString(fieldType, value);
        }
        public override object ToDbValue(Type fieldType, object value)
        {
            if (value is int && !fieldType.IsEnumFlags())
            {
                value = fieldType.GetEnumName(value);
            }

            if (fieldType.HasAttribute<EnumAsIntAttribute>())
            {
                if (value is string)
                {
                    value = Enum.Parse(fieldType, value.ToString());
                }
                return (int) value;
            }

            var enumValue = DialectProvider.StringSerializer.SerializeToString(value);
            // Oracle stores empty strings in varchar columns as null so match that behavior here
            if (enumValue == null)
                return null;
            enumValue = enumValue.Trim('"');
            return enumValue == ""
                ? null
                : enumValue;
        }
        public override object ToDbValue(Type fieldType, object value)
        {
            if (value is int && !fieldType.IsEnumFlags())
            {
                value = fieldType.GetEnumName(value);
            }

            var enumValue = DialectProvider.StringSerializer.SerializeToString(value);
            // Oracle stores empty strings in varchar columns as null so match that behavior here
            if (enumValue == null)
                return null;
            enumValue = enumValue.Trim('"');
            return enumValue == ""
                ? "null"
                : enumValue;
        }
        public override string ToQuotedString(Type fieldType, object value)
        {
            var isEnumFlags = fieldType.IsEnumFlags() ||
                (!fieldType.IsEnum && fieldType.IsNumericType()); //i.e. is real int && not Enum

            long enumValue;
            if (!isEnumFlags && long.TryParse(value.ToString(), out enumValue))
                value = Enum.ToObject(fieldType, enumValue);

            var enumString = DialectProvider.StringSerializer.SerializeToString(value);
            if (enumString == null || enumString == "null")
                enumString = value.ToString();

            return !isEnumFlags 
                ? DialectProvider.GetQuotedValue(enumString.Trim('"')) 
                : enumString;
        }
        public override string ToQuotedString(Type fieldType, object value)
        {
            var isEnumAsInt = fieldType.HasAttribute<EnumAsIntAttribute>();
            if (isEnumAsInt)
                return this.ConvertNumber(Enum.GetUnderlyingType(fieldType), value).ToString();

            var isEnumFlags = fieldType.IsEnumFlags() ||
                (!fieldType.IsEnum() && fieldType.IsNumericType()); //i.e. is real int && not Enum

            long enumValue;
            if (!isEnumFlags && long.TryParse(value.ToString(), out enumValue))
                value = Enum.ToObject(fieldType, enumValue);

            var enumString = DialectProvider.StringSerializer.SerializeToString(value);
            if (enumString == null || enumString == "null")
                enumString = value.ToString();

            return !isEnumFlags 
                ? DialectProvider.GetQuotedValue(enumString.Trim('"')) 
                : enumString;
        }
        public override object ToDbValue(Type fieldType, object value)
        {
            var isEnumFlags = fieldType.IsEnumFlags() ||
                (!fieldType.IsEnum && fieldType.IsNumericType()); //i.e. is real int && not Enum

            if (isEnumFlags && value.GetType().IsEnum)
                return Convert.ChangeType(value, fieldType.GetTypeCode());

            long enumValue;
            if (long.TryParse(value.ToString(), out enumValue))
            {
                if (isEnumFlags)
                    return enumValue;

                value = Enum.ToObject(fieldType, enumValue);
            }

            var enumString = DialectProvider.StringSerializer.SerializeToString(value);
            return enumString != null && enumString != "null"
                ? enumString.Trim('"') 
                : value.ToString();
        }
        public MetadataType ToType(Type type)
        {
            if (type == null) 
                return null;

            if (type.IsGenericType())
                type = type.GetGenericTypeDefinition();

            var metaType = new MetadataType
            {
                Name = type.GetOperationName(),
                Namespace = type.Namespace,
                GenericArgs = type.IsGenericType() ? GetGenericArgs(type) : null,
                Implements = ToInterfaces(type),
                Attributes = ToAttributes(type),
                Properties = ToProperties(type),
                IsNested = type.IsNested ? true : (bool?)null,
                IsEnum = type.IsEnum() ? true : (bool?)null,
                IsEnumInt = JsConfig.TreatEnumAsInteger || type.IsEnumFlags() ? true : (bool?)null,
                IsInterface = type.IsInterface() ? true : (bool?)null,
                IsAbstract = type.IsAbstract() ? true : (bool?)null,
            };

            if (type.BaseType() != null && type.BaseType() != typeof(object) && !type.IsEnum()
                && !type.HasInterface(typeof(IService)))
            {
                metaType.Inherits = ToTypeName(type.BaseType());
            }

            if (type.GetTypeWithInterfaceOf(typeof(IReturnVoid)) != null)
            {
                metaType.ReturnVoidMarker = true;
            }
            else
            {
                var genericMarker = type != typeof(IReturn<>)
                    ? type.GetTypeWithGenericTypeDefinitionOf(typeof(IReturn<>))
                    : null;

                if (genericMarker != null)
                {
                    var returnType = genericMarker.GetGenericArguments().First();
                    metaType.ReturnMarkerTypeName = ToTypeName(returnType);
                }
            }

            var routeAttrs = HostContext.AppHost.GetRouteAttributes(type).ToList();
            if (routeAttrs.Count > 0)
            {
                metaType.Routes = routeAttrs.ConvertAll(x =>
                    new MetadataRoute
                    {
                        Path = x.Path,
                        Notes = x.Notes,
                        Summary = x.Summary,
                        Verbs = x.Verbs,
                    });
            }

            metaType.Description = type.GetDescription();

            var dcAttr = type.GetDataContract();
            if (dcAttr != null)
            {
                metaType.DataContract = new MetadataDataContract
                {
                    Name = dcAttr.Name,
                    Namespace = dcAttr.Namespace,
                };
            }

            if (type.IsEnum())
            {
                metaType.EnumNames = new List<string>();
                metaType.EnumValues = new List<string>();

                var isDefaultLayout = true;
                var values = Enum.GetValues(type);
                for (var i = 0; i < values.Length; i++)
                {
                    var value = values.GetValue(i);
                    var name = value.ToString();
                    var enumValue = Convert.ToInt64(value).ToString();

                    if (enumValue != i.ToString())
                        isDefaultLayout = false;

                    metaType.EnumNames.Add(name);
                    metaType.EnumValues.Add(enumValue);
                }

                if (isDefaultLayout)
                    metaType.EnumValues = null;
            }

            var innerTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
            foreach (var innerType in innerTypes)
            {
                if (metaType.InnerTypes == null)
                    metaType.InnerTypes = new List<MetadataTypeName>();

                metaType.InnerTypes.Add(new MetadataTypeName
                {
                    Name = innerType.GetOperationName(),
                    Namespace = innerType.Namespace,
                    GenericArgs = innerType.IsGenericType()
                        ? innerType.GetGenericArguments().Select(x => x.GetOperationName()).ToArray()
                        : null,
                });
            }

            return metaType;
        }