Mercurial > pub > bltoolkit
diff Source/Data/Sql/SqlValueBase.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Data/Sql/SqlValueBase.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using BLToolkit.Mapping; +using BLToolkit.Reflection; + +namespace BLToolkit.Data.Sql +{ + public abstract class SqlValueBase: IValueContainer + { + [CLSCompliant(false)] + protected object _value; + public virtual object Value + { + get + { + var valueConverter = ValueConverter; + return valueConverter == null ? _value : valueConverter(_value); + } + + set { _value = value; } + } + + #region Value Converter + + internal List<Type> EnumTypes; + internal List<int> TakeValues; + internal string LikeStart, LikeEnd; + + private Converter<object,object> _valueConverter; + public Converter<object,object> ValueConverter + { + get + { + if (_valueConverter == null) + { + if (EnumTypes != null) + foreach (var type in EnumTypes.ToArray()) + SetEnumConverter(type, Map.DefaultSchema); + else if (TakeValues != null) + foreach (var take in TakeValues.ToArray()) + SetTakeConverter(take); + else if (LikeStart != null) + SetLikeConverter(LikeStart, LikeEnd); + } + + return _valueConverter; + } + + set { _valueConverter = value; } + } + + bool _isEnumConverterSet; + + internal void SetEnumConverter(Type type, MappingSchema ms) + { + if (!_isEnumConverterSet) + { + _isEnumConverterSet = true; + + if (EnumTypes == null) + EnumTypes = new List<Type>(); + + EnumTypes.Add(type); + + SetEnumConverterInternal(type, ms); + } + } + + internal void SetEnumConverter(MemberAccessor ma, MappingSchema ms) + { + if (!_isEnumConverterSet) + { + _isEnumConverterSet = true; + + if (EnumTypes == null) + EnumTypes = new List<Type>(); + + EnumTypes.Add(ma.Type); + + SetEnumConverterInternal(ma, ms); + } + } + + void SetEnumConverterInternal(MemberAccessor ma, MappingSchema ms) + { + if (_valueConverter == null) + { + _valueConverter = o => ms.MapEnumToValue(o, ma, true); + } + else + { + var converter = _valueConverter; + _valueConverter = o => ms.MapEnumToValue(converter(o), ma, true); + } + // update system type in SqlValue :-/ + var tmp = Value; + } + + void SetEnumConverterInternal(Type type, MappingSchema ms) + { + if (_valueConverter == null) + { + _valueConverter = o => ms.MapEnumToValue(o, type, true); + } + else + { + var converter = _valueConverter; + _valueConverter = o => ms.MapEnumToValue(converter(o), type, true); + } + // update system type in SqlValue :-/ + var tmp = Value; + } + + internal void SetTakeConverter(int take) + { + if (TakeValues == null) + TakeValues = new List<int>(); + + TakeValues.Add(take); + + SetTakeConverterInternal(take); + } + + void SetTakeConverterInternal(int take) + { + var conv = _valueConverter; + + if (conv == null) + _valueConverter = v => v == null ? null : (object)((int)v + take); + else + _valueConverter = v => v == null ? null : (object)((int)conv(v) + take); + } + + internal void SetLikeConverter(string start, string end) + { + LikeStart = start; + LikeEnd = end; + _valueConverter = GetLikeEscaper(start, end); + } + + static Converter<object, object> GetLikeEscaper(string start, string end) + { + return value => + { + if (value == null) + #if DEBUG + value = ""; + #else + throw new SqlException("NULL cannot be used as a LIKE predicate parameter."); + #endif + + var text = value.ToString(); + + if (text.IndexOfAny(new[] { '%', '_', '[' }) < 0) + return start + text + end; + + var sb = new StringBuilder(start, text.Length + start.Length + end.Length); + + foreach (var c in text) + { + if (c == '%' || c == '_' || c == '[') + { + sb.Append('['); + sb.Append(c); + sb.Append(']'); + } + else + sb.Append(c); + } + + return sb.ToString(); + }; + } + + #endregion + } +}